2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 #include "cl_dyntexture.h"
30 #include "dpsoftrast.h"
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
37 mempool_t *r_main_mempool;
38 rtexturepool_t *r_main_texturepool;
40 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
42 static qboolean r_loadnormalmap;
43 static qboolean r_loadgloss;
45 static qboolean r_loaddds;
46 static qboolean r_savedds;
53 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
55 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
56 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
57 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
58 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
59 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
60 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
62 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
63 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
64 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
65 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
66 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
68 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
69 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
70 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
71 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
72 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
73 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
74 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
75 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
76 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
77 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
78 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
79 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
80 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
81 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
82 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
83 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
84 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
85 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
86 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
87 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
88 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
89 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
90 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
91 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
92 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
93 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
94 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
95 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
97 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
98 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
99 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
101 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
102 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
103 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
104 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
105 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
106 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
107 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
108 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
109 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
110 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
111 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
112 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
113 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
114 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
115 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
116 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
117 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
118 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
119 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
121 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
122 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
123 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
124 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
125 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
126 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
127 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
128 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
130 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
131 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
133 cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
134 cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
135 cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
136 cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
137 cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
139 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
140 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
141 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
143 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
144 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
145 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
146 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
147 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
148 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
149 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
150 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
151 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
152 cvar_t r_glsl_postprocess_uservec1_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec1_enable", "1", "enables postprocessing uservec1 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
153 cvar_t r_glsl_postprocess_uservec2_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec2_enable", "1", "enables postprocessing uservec2 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
154 cvar_t r_glsl_postprocess_uservec3_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec3_enable", "1", "enables postprocessing uservec3 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
155 cvar_t r_glsl_postprocess_uservec4_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec4_enable", "1", "enables postprocessing uservec4 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
157 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
158 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
159 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
160 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
161 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
162 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
164 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
165 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
166 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
167 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
169 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
170 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
171 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
172 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
173 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
174 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
175 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
177 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
178 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
179 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
180 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivalent to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
181 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
182 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
183 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
184 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
185 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
186 cvar_t r_hdr_irisadaptation_fade = {CVAR_SAVE, "r_hdr_irisadaptation_fade", "1", "fade rate at which value adjusts"};
188 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
190 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
192 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
194 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
195 cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
196 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accordingly, 2: Make it a continuous rotation"};
197 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
198 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
199 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "5", "fake perspective effect for SPR_OVERHEAD sprites"};
200 cvar_t r_overheadsprites_pushback = {CVAR_SAVE, "r_overheadsprites_pushback", "15", "how far to pull the SPR_OVERHEAD sprites toward the eye (used to avoid intersections with 3D models)"};
201 cvar_t r_overheadsprites_scalex = {CVAR_SAVE, "r_overheadsprites_scalex", "1", "additional scale for overhead sprites for x axis"};
202 cvar_t r_overheadsprites_scaley = {CVAR_SAVE, "r_overheadsprites_scaley", "1", "additional scale for overhead sprites for y axis"};
204 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
205 cvar_t r_glsl_saturation_redcompensate = {CVAR_SAVE, "r_glsl_saturation_redcompensate", "0", "a 'vampire sight' addition to desaturation effect, does compensation for red color, r_glsl_restart is required"};
207 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "0.5", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
209 extern cvar_t v_glslgamma;
211 extern qboolean v_flipped_state;
213 static struct r_bloomstate_s
218 int bloomwidth, bloomheight;
220 int screentexturewidth, screentextureheight;
221 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
223 int bloomtexturewidth, bloomtextureheight;
224 rtexture_t *texture_bloom;
226 // arrays for rendering the screen passes
227 float screentexcoord2f[8];
228 float bloomtexcoord2f[8];
229 float offsettexcoord2f[8];
231 r_viewport_t viewport;
235 r_waterstate_t r_waterstate;
237 /// shadow volume bsp struct with automatically growing nodes buffer
240 rtexture_t *r_texture_blanknormalmap;
241 rtexture_t *r_texture_white;
242 rtexture_t *r_texture_grey128;
243 rtexture_t *r_texture_black;
244 rtexture_t *r_texture_notexture;
245 rtexture_t *r_texture_whitecube;
246 rtexture_t *r_texture_normalizationcube;
247 rtexture_t *r_texture_fogattenuation;
248 rtexture_t *r_texture_fogheighttexture;
249 rtexture_t *r_texture_gammaramps;
250 unsigned int r_texture_gammaramps_serial;
251 //rtexture_t *r_texture_fogintensity;
252 rtexture_t *r_texture_reflectcube;
254 // TODO: hash lookups?
255 typedef struct cubemapinfo_s
262 int r_texture_numcubemaps;
263 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
265 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
266 unsigned int r_numqueries;
267 unsigned int r_maxqueries;
269 typedef struct r_qwskincache_s
271 char name[MAX_QPATH];
272 skinframe_t *skinframe;
276 static r_qwskincache_t *r_qwskincache;
277 static int r_qwskincache_size;
279 /// vertex coordinates for a quad that covers the screen exactly
280 extern const float r_screenvertex3f[12];
281 extern const float r_d3dscreenvertex3f[12];
282 const float r_screenvertex3f[12] =
289 const float r_d3dscreenvertex3f[12] =
297 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
300 for (i = 0;i < verts;i++)
311 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
314 for (i = 0;i < verts;i++)
324 // FIXME: move this to client?
327 if (gamemode == GAME_NEHAHRA)
329 Cvar_Set("gl_fogenable", "0");
330 Cvar_Set("gl_fogdensity", "0.2");
331 Cvar_Set("gl_fogred", "0.3");
332 Cvar_Set("gl_foggreen", "0.3");
333 Cvar_Set("gl_fogblue", "0.3");
335 r_refdef.fog_density = 0;
336 r_refdef.fog_red = 0;
337 r_refdef.fog_green = 0;
338 r_refdef.fog_blue = 0;
339 r_refdef.fog_alpha = 1;
340 r_refdef.fog_start = 0;
341 r_refdef.fog_end = 16384;
342 r_refdef.fog_height = 1<<30;
343 r_refdef.fog_fadedepth = 128;
344 memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
347 static void R_BuildBlankTextures(void)
349 unsigned char data[4];
350 data[2] = 128; // normal X
351 data[1] = 128; // normal Y
352 data[0] = 255; // normal Z
353 data[3] = 128; // height
354 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
359 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
364 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
369 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
372 static void R_BuildNoTexture(void)
375 unsigned char pix[16][16][4];
376 // this makes a light grey/dark grey checkerboard texture
377 for (y = 0;y < 16;y++)
379 for (x = 0;x < 16;x++)
381 if ((y < 8) ^ (x < 8))
397 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
400 static void R_BuildWhiteCube(void)
402 unsigned char data[6*1*1*4];
403 memset(data, 255, sizeof(data));
404 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
407 static void R_BuildNormalizationCube(void)
411 vec_t s, t, intensity;
414 data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
415 for (side = 0;side < 6;side++)
417 for (y = 0;y < NORMSIZE;y++)
419 for (x = 0;x < NORMSIZE;x++)
421 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
422 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
457 intensity = 127.0f / sqrt(DotProduct(v, v));
458 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
459 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
460 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
461 data[((side*64+y)*64+x)*4+3] = 255;
465 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
469 static void R_BuildFogTexture(void)
473 unsigned char data1[FOGWIDTH][4];
474 //unsigned char data2[FOGWIDTH][4];
477 r_refdef.fogmasktable_start = r_refdef.fog_start;
478 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
479 r_refdef.fogmasktable_range = r_refdef.fogrange;
480 r_refdef.fogmasktable_density = r_refdef.fog_density;
482 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
483 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
485 d = (x * r - r_refdef.fogmasktable_start);
486 if(developer_extra.integer)
487 Con_DPrintf("%f ", d);
489 if (r_fog_exp2.integer)
490 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
492 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
493 if(developer_extra.integer)
494 Con_DPrintf(" : %f ", alpha);
495 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
496 if(developer_extra.integer)
497 Con_DPrintf(" = %f\n", alpha);
498 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
501 for (x = 0;x < FOGWIDTH;x++)
503 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
508 //data2[x][0] = 255 - b;
509 //data2[x][1] = 255 - b;
510 //data2[x][2] = 255 - b;
513 if (r_texture_fogattenuation)
515 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
516 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
520 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
521 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
525 static void R_BuildFogHeightTexture(void)
527 unsigned char *inpixels;
535 strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
536 if (r_refdef.fogheighttexturename[0])
537 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
540 r_refdef.fog_height_tablesize = 0;
541 if (r_texture_fogheighttexture)
542 R_FreeTexture(r_texture_fogheighttexture);
543 r_texture_fogheighttexture = NULL;
544 if (r_refdef.fog_height_table2d)
545 Mem_Free(r_refdef.fog_height_table2d);
546 r_refdef.fog_height_table2d = NULL;
547 if (r_refdef.fog_height_table1d)
548 Mem_Free(r_refdef.fog_height_table1d);
549 r_refdef.fog_height_table1d = NULL;
553 r_refdef.fog_height_tablesize = size;
554 r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
555 r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
556 memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
558 // LordHavoc: now the magic - what is that table2d for? it is a cooked
559 // average fog color table accounting for every fog layer between a point
560 // and the camera. (Note: attenuation is handled separately!)
561 for (y = 0;y < size;y++)
563 for (x = 0;x < size;x++)
569 for (j = x;j <= y;j++)
571 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
577 for (j = x;j >= y;j--)
579 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
584 r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
585 r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
586 r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
587 r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
590 r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
593 //=======================================================================================================================================================
595 static const char *builtinshaderstring =
596 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
597 "// written by Forest 'LordHavoc' Hale\n"
598 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
600 "// GL ES shaders use precision modifiers, standard GL does not\n"
607 "#ifdef VERTEX_SHADER\n"
608 "attribute vec4 Attrib_Position; // vertex\n"
609 "attribute vec4 Attrib_Color; // color\n"
610 "attribute vec4 Attrib_TexCoord0; // material texcoords\n"
611 "attribute vec3 Attrib_TexCoord1; // svector\n"
612 "attribute vec3 Attrib_TexCoord2; // tvector\n"
613 "attribute vec3 Attrib_TexCoord3; // normal\n"
614 "attribute vec4 Attrib_TexCoord4; // lightmap texcoords\n"
616 "varying lowp vec4 VertexColor;\n"
618 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
621 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
622 "#define USELIGHTMAP\n"
624 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
625 "#define USEEYEVECTOR\n"
628 "#ifdef USESHADOWMAP2D\n"
629 "# ifdef GL_EXT_gpu_shader4\n"
630 "# extension GL_EXT_gpu_shader4 : enable\n"
632 "# ifdef GL_ARB_texture_gather\n"
633 "# extension GL_ARB_texture_gather : enable\n"
635 "# ifdef GL_AMD_texture_texture4\n"
636 "# extension GL_AMD_texture_texture4 : enable\n"
641 "//#ifdef USESHADOWSAMPLER\n"
642 "//# extension GL_ARB_shadow : enable\n"
645 "//#ifdef __GLSL_CG_DATA_TYPES\n"
646 "//# define myhalf half\n"
647 "//# define myhalf2 half2\n"
648 "//# define myhalf3 half3\n"
649 "//# define myhalf4 half4\n"
651 "# define myhalf mediump float\n"
652 "# define myhalf2 mediump vec2\n"
653 "# define myhalf3 mediump vec3\n"
654 "# define myhalf4 mediump vec4\n"
657 "#ifdef VERTEX_SHADER\n"
658 "uniform highp mat4 ModelViewProjectionMatrix;\n"
661 "#ifdef MODE_DEPTH_OR_SHADOW\n"
662 "#ifdef VERTEX_SHADER\n"
665 " gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
668 "#else // !MODE_DEPTH_ORSHADOW\n"
673 "#ifdef MODE_SHOWDEPTH\n"
674 "#ifdef VERTEX_SHADER\n"
677 " gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
678 " VertexColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
682 "#ifdef FRAGMENT_SHADER\n"
685 " gl_FragColor = VertexColor;\n"
688 "#else // !MODE_SHOWDEPTH\n"
693 "#ifdef MODE_POSTPROCESS\n"
694 "varying mediump vec2 TexCoord1;\n"
695 "varying mediump vec2 TexCoord2;\n"
697 "#ifdef VERTEX_SHADER\n"
700 " gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
701 " TexCoord1 = Attrib_TexCoord0.xy;\n"
703 " TexCoord2 = Attrib_TexCoord4.xy;\n"
708 "#ifdef FRAGMENT_SHADER\n"
709 "uniform sampler2D Texture_First;\n"
711 "uniform sampler2D Texture_Second;\n"
712 "uniform lowp vec4 BloomColorSubtract;\n"
714 "#ifdef USEGAMMARAMPS\n"
715 "uniform sampler2D Texture_GammaRamps;\n"
717 "#ifdef USESATURATION\n"
718 "uniform lowp float Saturation;\n"
720 "#ifdef USEVIEWTINT\n"
721 "uniform lowp vec4 ViewTintColor;\n"
723 "//uncomment these if you want to use them:\n"
724 "uniform mediump vec4 UserVec1;\n"
725 "uniform mediump vec4 UserVec2;\n"
726 "// uniform mediump vec4 UserVec3;\n"
727 "// uniform mediump vec4 UserVec4;\n"
728 "// uniform highp float ClientTime;\n"
729 "uniform mediump vec2 PixelSize;\n"
732 " gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
734 " gl_FragColor += max(vec4(0,0,0,0), texture2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
736 "#ifdef USEVIEWTINT\n"
737 " gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
740 "#ifdef USEPOSTPROCESSING\n"
741 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
742 "// this code does a blur with the radius specified in the first component of r_glsl_postprocess_uservec1 and blends it using the second component\n"
743 " float sobel = 1.0;\n"
744 " // vec2 ts = textureSize(Texture_First, 0);\n"
745 " // vec2 px = vec2(1/ts.x, 1/ts.y);\n"
746 " vec2 px = PixelSize;\n"
747 " vec3 x1 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
748 " vec3 x2 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, 0.0)).rgb;\n"
749 " vec3 x3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
750 " vec3 x4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
751 " vec3 x5 = texture2D(Texture_First, TexCoord1 + vec2( px.x, 0.0)).rgb;\n"
752 " vec3 x6 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
753 " vec3 y1 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
754 " vec3 y2 = texture2D(Texture_First, TexCoord1 + vec2( 0.0,-px.y)).rgb;\n"
755 " vec3 y3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
756 " vec3 y4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
757 " vec3 y5 = texture2D(Texture_First, TexCoord1 + vec2( 0.0, px.y)).rgb;\n"
758 " vec3 y6 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
759 " float px1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x1);\n"
760 " float px2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), x2);\n"
761 " float px3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x3);\n"
762 " float px4 = 1.0 * dot(vec3(0.3, 0.59, 0.11), x4);\n"
763 " float px5 = 2.0 * dot(vec3(0.3, 0.59, 0.11), x5);\n"
764 " float px6 = 1.0 * dot(vec3(0.3, 0.59, 0.11), x6);\n"
765 " float py1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y1);\n"
766 " float py2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), y2);\n"
767 " float py3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y3);\n"
768 " float py4 = 1.0 * dot(vec3(0.3, 0.59, 0.11), y4);\n"
769 " float py5 = 2.0 * dot(vec3(0.3, 0.59, 0.11), y5);\n"
770 " float py6 = 1.0 * dot(vec3(0.3, 0.59, 0.11), y6);\n"
771 " sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
772 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
773 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
774 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
775 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107, 0.707107)) * UserVec1.y;\n"
776 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990, 0.891007)) * UserVec1.y;\n"
777 " gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
778 " gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + vec3(max(0.0, sobel - UserVec2.z))*UserVec2.y;\n"
781 "#ifdef USESATURATION\n"
782 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
783 " float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
784 " // 'vampire sight' effect, wheres red is compensated\n"
785 " #ifdef SATURATION_REDCOMPENSATE\n"
786 " float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n"
787 " gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
788 " gl_FragColor.r += rboost;\n"
790 " // normal desaturation\n"
791 " //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
792 " gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
796 "#ifdef USEGAMMARAMPS\n"
797 " gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
798 " gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
799 " gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
803 "#else // !MODE_POSTPROCESS\n"
808 "#ifdef MODE_GENERIC\n"
809 "#ifdef USEDIFFUSE\n"
810 "varying mediump vec2 TexCoord1;\n"
812 "#ifdef USESPECULAR\n"
813 "varying mediump vec2 TexCoord2;\n"
815 "#ifdef VERTEX_SHADER\n"
818 " VertexColor = Attrib_Color;\n"
819 "#ifdef USEDIFFUSE\n"
820 " TexCoord1 = Attrib_TexCoord0.xy;\n"
822 "#ifdef USESPECULAR\n"
823 " TexCoord2 = Attrib_TexCoord1.xy;\n"
825 " gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
829 "#ifdef FRAGMENT_SHADER\n"
830 "#ifdef USEDIFFUSE\n"
831 "uniform sampler2D Texture_First;\n"
833 "#ifdef USESPECULAR\n"
834 "uniform sampler2D Texture_Second;\n"
839 "#ifdef USEVIEWTINT\n"
840 " gl_FragColor = VertexColor;\n"
842 " gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
844 "#ifdef USEDIFFUSE\n"
845 " gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
848 "#ifdef USESPECULAR\n"
849 " vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
850 "# ifdef USECOLORMAPPING\n"
851 " gl_FragColor *= tex2;\n"
854 " gl_FragColor += tex2;\n"
856 "# ifdef USEVERTEXTEXTUREBLEND\n"
857 " gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
862 "#else // !MODE_GENERIC\n"
867 "#ifdef MODE_BLOOMBLUR\n"
868 "varying mediump vec2 TexCoord;\n"
869 "#ifdef VERTEX_SHADER\n"
872 " VertexColor = Attrib_Color;\n"
873 " TexCoord = Attrib_TexCoord0.xy;\n"
874 " gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
878 "#ifdef FRAGMENT_SHADER\n"
879 "uniform sampler2D Texture_First;\n"
880 "uniform mediump vec4 BloomBlur_Parameters;\n"
885 " vec2 tc = TexCoord;\n"
886 " vec3 color = texture2D(Texture_First, tc).rgb;\n"
887 " tc += BloomBlur_Parameters.xy;\n"
888 " for (i = 1;i < SAMPLES;i++)\n"
890 " color += texture2D(Texture_First, tc).rgb;\n"
891 " tc += BloomBlur_Parameters.xy;\n"
893 " gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
896 "#else // !MODE_BLOOMBLUR\n"
897 "#ifdef MODE_REFRACTION\n"
898 "varying mediump vec2 TexCoord;\n"
899 "varying highp vec4 ModelViewProjectionPosition;\n"
900 "uniform highp mat4 TexMatrix;\n"
901 "#ifdef VERTEX_SHADER\n"
905 " TexCoord = vec2(TexMatrix * Attrib_TexCoord0);\n"
906 " gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
907 " ModelViewProjectionPosition = gl_Position;\n"
911 "#ifdef FRAGMENT_SHADER\n"
912 "uniform sampler2D Texture_Normal;\n"
913 "uniform sampler2D Texture_Refraction;\n"
914 "uniform sampler2D Texture_Reflection;\n"
916 "uniform mediump vec4 DistortScaleRefractReflect;\n"
917 "uniform mediump vec4 ScreenScaleRefractReflect;\n"
918 "uniform mediump vec4 ScreenCenterRefractReflect;\n"
919 "uniform lowp vec4 RefractColor;\n"
920 "uniform lowp vec4 ReflectColor;\n"
921 "uniform mediump float ReflectFactor;\n"
922 "uniform mediump float ReflectOffset;\n"
926 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
927 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
928 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
929 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
930 " // FIXME temporary hack to detect the case that the reflection\n"
931 " // gets blackened at edges due to leaving the area that contains actual\n"
933 " // Remove this 'ack once we have a better way to stop this thing from\n"
935 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
936 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
937 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
938 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
939 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
940 " gl_FragColor = vec4(texture2D(Texture_Refraction, ScreenTexCoord).rgb, 1.0) * RefractColor;\n"
943 "#else // !MODE_REFRACTION\n"
948 "#ifdef MODE_WATER\n"
949 "varying mediump vec2 TexCoord;\n"
950 "varying highp vec3 EyeVector;\n"
951 "varying highp vec4 ModelViewProjectionPosition;\n"
952 "#ifdef VERTEX_SHADER\n"
953 "uniform highp vec3 EyePosition;\n"
954 "uniform highp mat4 TexMatrix;\n"
958 " TexCoord = vec2(TexMatrix * Attrib_TexCoord0);\n"
959 " vec3 EyeVectorModelSpace = EyePosition - Attrib_Position.xyz;\n"
960 " EyeVector.x = dot(EyeVectorModelSpace, Attrib_TexCoord1.xyz);\n"
961 " EyeVector.y = dot(EyeVectorModelSpace, Attrib_TexCoord2.xyz);\n"
962 " EyeVector.z = dot(EyeVectorModelSpace, Attrib_TexCoord3.xyz);\n"
963 " gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
964 " ModelViewProjectionPosition = gl_Position;\n"
968 "#ifdef FRAGMENT_SHADER\n"
969 "uniform sampler2D Texture_Normal;\n"
970 "uniform sampler2D Texture_Refraction;\n"
971 "uniform sampler2D Texture_Reflection;\n"
973 "uniform mediump vec4 DistortScaleRefractReflect;\n"
974 "uniform mediump vec4 ScreenScaleRefractReflect;\n"
975 "uniform mediump vec4 ScreenCenterRefractReflect;\n"
976 "uniform lowp vec4 RefractColor;\n"
977 "uniform lowp vec4 ReflectColor;\n"
978 "uniform mediump float ReflectFactor;\n"
979 "uniform mediump float ReflectOffset;\n"
980 "uniform highp float ClientTime;\n"
981 "#ifdef USENORMALMAPSCROLLBLEND\n"
982 "uniform highp vec2 NormalmapScrollBlend;\n"
987 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
988 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
989 " vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
990 " //SafeScreenTexCoord = gl_FragCoord.xyxy * vec4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
991 " // slight water animation via 2 layer scrolling (todo: tweak)\n"
992 " #ifdef USENORMALMAPSCROLLBLEND\n"
993 " vec3 normal = texture2D(Texture_Normal, (TexCoord + vec2(0.08, 0.08)*ClientTime*NormalmapScrollBlend.x*0.5)*NormalmapScrollBlend.y).rgb - vec3(1.0);\n"
994 " normal += texture2D(Texture_Normal, (TexCoord + vec2(-0.06, -0.09)*ClientTime*NormalmapScrollBlend.x)*NormalmapScrollBlend.y*0.75).rgb;\n"
995 " vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(normal) + vec3(0.15)).xyxy * DistortScaleRefractReflect;\n"
997 " vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
999 " // FIXME temporary hack to detect the case that the reflection\n"
1000 " // gets blackened at edges due to leaving the area that contains actual\n"
1002 " // Remove this 'ack once we have a better way to stop this thing from\n"
1004 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.005, 0.01)).rgb) / 0.002);\n"
1005 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.005, -0.01)).rgb) / 0.002);\n"
1006 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, 0.01)).rgb) / 0.002);\n"
1007 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, -0.01)).rgb) / 0.002);\n"
1008 " ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
1009 " f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.005, 0.005)).rgb) / 0.002);\n"
1010 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.005, -0.005)).rgb) / 0.002);\n"
1011 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, 0.005)).rgb) / 0.002);\n"
1012 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, -0.005)).rgb) / 0.002);\n"
1013 " ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
1014 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
1015 " gl_FragColor = mix(vec4(texture2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, vec4(texture2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
1018 "#else // !MODE_WATER\n"
1023 "// common definitions between vertex shader and fragment shader:\n"
1025 "varying mediump vec2 TexCoord;\n"
1026 "#ifdef USEVERTEXTEXTUREBLEND\n"
1027 "varying mediump vec2 TexCoord2;\n"
1029 "#ifdef USELIGHTMAP\n"
1030 "varying mediump vec2 TexCoordLightmap;\n"
1033 "#ifdef MODE_LIGHTSOURCE\n"
1034 "varying mediump vec3 CubeVector;\n"
1037 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
1038 "varying mediump vec3 LightVector;\n"
1041 "#ifdef USEEYEVECTOR\n"
1042 "varying highp vec3 EyeVector;\n"
1045 "varying highp vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
1048 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
1049 "varying lowp vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
1050 "varying lowp vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
1051 "varying lowp vec3 VectorR; // direction of R texcoord (surface normal)\n"
1054 "#ifdef USEREFLECTION\n"
1055 "varying highp vec4 ModelViewProjectionPosition;\n"
1057 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1058 "uniform highp vec3 LightPosition;\n"
1059 "varying highp vec4 ModelViewPosition;\n"
1062 "#ifdef MODE_LIGHTSOURCE\n"
1063 "uniform highp vec3 LightPosition;\n"
1065 "uniform highp vec3 EyePosition;\n"
1066 "#ifdef MODE_LIGHTDIRECTION\n"
1067 "uniform highp vec3 LightDir;\n"
1069 "uniform highp vec4 FogPlane;\n"
1071 "#ifdef USESHADOWMAPORTHO\n"
1072 "varying mediump vec3 ShadowMapTC;\n"
1075 "#ifdef USEBOUNCEGRID\n"
1076 "varying mediump vec3 BounceGridTexCoord;\n"
1084 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3), this would require sending a 4 component texcoord1 with W as 1 or -1 according to which side the texcoord2 should be on\n"
1086 "// fragment shader specific:\n"
1087 "#ifdef FRAGMENT_SHADER\n"
1089 "uniform sampler2D Texture_Normal;\n"
1090 "uniform sampler2D Texture_Color;\n"
1091 "uniform sampler2D Texture_Gloss;\n"
1093 "uniform sampler2D Texture_Glow;\n"
1095 "#ifdef USEVERTEXTEXTUREBLEND\n"
1096 "uniform sampler2D Texture_SecondaryNormal;\n"
1097 "uniform sampler2D Texture_SecondaryColor;\n"
1098 "uniform sampler2D Texture_SecondaryGloss;\n"
1100 "uniform sampler2D Texture_SecondaryGlow;\n"
1103 "#ifdef USECOLORMAPPING\n"
1104 "uniform sampler2D Texture_Pants;\n"
1105 "uniform sampler2D Texture_Shirt;\n"
1108 "#ifdef USEFOGHEIGHTTEXTURE\n"
1109 "uniform sampler2D Texture_FogHeightTexture;\n"
1111 "uniform sampler2D Texture_FogMask;\n"
1113 "#ifdef USELIGHTMAP\n"
1114 "uniform sampler2D Texture_Lightmap;\n"
1116 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1117 "uniform sampler2D Texture_Deluxemap;\n"
1119 "#ifdef USEREFLECTION\n"
1120 "uniform sampler2D Texture_Reflection;\n"
1123 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1124 "uniform sampler2D Texture_ScreenDepth;\n"
1125 "uniform sampler2D Texture_ScreenNormalMap;\n"
1127 "#ifdef USEDEFERREDLIGHTMAP\n"
1128 "uniform sampler2D Texture_ScreenDiffuse;\n"
1129 "uniform sampler2D Texture_ScreenSpecular;\n"
1132 "uniform lowp vec3 Color_Pants;\n"
1133 "uniform lowp vec3 Color_Shirt;\n"
1134 "uniform lowp vec3 FogColor;\n"
1137 "uniform highp float FogRangeRecip;\n"
1138 "uniform highp float FogPlaneViewDist;\n"
1139 "uniform highp float FogHeightFade;\n"
1140 "vec3 FogVertex(vec3 surfacecolor)\n"
1142 " vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
1143 " float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
1145 "#ifdef USEFOGHEIGHTTEXTURE\n"
1146 " vec4 fogheightpixel = texture2D(Texture_FogHeightTexture, vec2(1,1) + vec2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
1147 " fogfrac = fogheightpixel.a;\n"
1148 " return mix(fogheightpixel.rgb * FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1150 "# ifdef USEFOGOUTSIDE\n"
1151 " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1153 " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1155 " return mix(FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1160 "#ifdef USEOFFSETMAPPING\n"
1161 "uniform mediump float OffsetMapping_Scale;\n"
1162 "vec2 OffsetMapping(vec2 TexCoord)\n"
1164 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
1165 " // 14 sample relief mapping: linear search and then binary search\n"
1166 " // this basically steps forward a small amount repeatedly until it finds\n"
1167 " // itself inside solid, then jitters forward and back using decreasing\n"
1168 " // amounts to find the impact\n"
1169 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
1170 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1171 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1172 " vec3 RT = vec3(TexCoord, 1);\n"
1173 " OffsetVector *= 0.1;\n"
1174 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1175 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1176 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1177 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1178 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1179 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1180 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1181 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1182 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1183 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
1184 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
1185 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
1186 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
1187 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1190 " // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1191 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1192 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1193 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1194 " OffsetVector *= 0.5;\n"
1195 " TexCoord += OffsetVector * (1.0 - texture2D(Texture_Normal, TexCoord).a);\n"
1196 " TexCoord += OffsetVector * (1.0 - texture2D(Texture_Normal, TexCoord).a);\n"
1197 " return TexCoord;\n"
1200 "#endif // USEOFFSETMAPPING\n"
1202 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1203 "uniform sampler2D Texture_Attenuation;\n"
1204 "uniform samplerCube Texture_Cube;\n"
1207 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
1209 "#ifdef USESHADOWMAP2D\n"
1210 "# ifdef USESHADOWSAMPLER\n"
1211 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1213 "uniform sampler2D Texture_ShadowMap2D;\n"
1217 "#ifdef USESHADOWMAPVSDCT\n"
1218 "uniform samplerCube Texture_CubeProjection;\n"
1221 "#if defined(USESHADOWMAP2D)\n"
1222 "uniform mediump vec2 ShadowMap_TextureScale;\n"
1223 "uniform mediump vec4 ShadowMap_Parameters;\n"
1226 "#if defined(USESHADOWMAP2D)\n"
1227 "# ifdef USESHADOWMAPORTHO\n"
1228 "# define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n"
1230 "# ifdef USESHADOWMAPVSDCT\n"
1231 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1233 " vec3 adir = abs(dir);\n"
1234 " vec2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
1235 " vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1236 " return vec3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1239 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1241 " vec3 adir = abs(dir);\n"
1242 " float ma = adir.z;\n"
1243 " vec4 proj = vec4(dir, 2.5);\n"
1244 " if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
1245 " if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
1246 " vec2 aparams = ShadowMap_Parameters.xy / ma;\n"
1247 " return vec3(proj.xy * aparams.x + vec2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1251 "#endif // defined(USESHADOWMAP2D)\n"
1253 "# ifdef USESHADOWMAP2D\n"
1254 "float ShadowMapCompare(vec3 dir)\n"
1256 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1259 "# ifdef USESHADOWSAMPLER\n"
1260 "# ifdef USESHADOWMAPPCF\n"
1261 "# define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r \n"
1262 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1263 " f = dot(vec4(0.25), vec4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
1265 " f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1268 "# ifdef USESHADOWMAPPCF\n"
1269 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1270 "# ifdef GL_ARB_texture_gather\n"
1271 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1273 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1275 " vec2 offset = fract(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
1276 "# if USESHADOWMAPPCF > 1\n"
1277 " vec4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
1278 " vec4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
1279 " vec4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
1280 " vec4 group4 = step(shadowmaptc.z, texval(-2.0, 0.0));\n"
1281 " vec4 group5 = step(shadowmaptc.z, texval( 0.0, 0.0));\n"
1282 " vec4 group6 = step(shadowmaptc.z, texval( 2.0, 0.0));\n"
1283 " vec4 group7 = step(shadowmaptc.z, texval(-2.0, 2.0));\n"
1284 " vec4 group8 = step(shadowmaptc.z, texval( 0.0, 2.0));\n"
1285 " vec4 group9 = step(shadowmaptc.z, texval( 2.0, 2.0));\n"
1286 " vec4 locols = vec4(group1.ab, group3.ab);\n"
1287 " vec4 hicols = vec4(group7.rg, group9.rg);\n"
1288 " locols.yz += group2.ab;\n"
1289 " hicols.yz += group8.rg;\n"
1290 " vec4 midcols = vec4(group1.rg, group3.rg) + vec4(group7.ab, group9.ab) +\n"
1291 " vec4(group4.rg, group6.rg) + vec4(group4.ab, group6.ab) +\n"
1292 " mix(locols, hicols, offset.y);\n"
1293 " vec4 cols = group5 + vec4(group2.rg, group8.ab);\n"
1294 " cols.xyz += mix(midcols.xyz, midcols.yzw, offset.x);\n"
1295 " f = dot(cols, vec4(1.0/25.0));\n"
1297 " vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1298 " vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1299 " vec4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
1300 " vec4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
1301 " vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1302 " mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1303 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1306 "# ifdef GL_EXT_gpu_shader4\n"
1307 "# define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1309 "# define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r \n"
1311 "# if USESHADOWMAPPCF > 1\n"
1312 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1313 " center *= ShadowMap_TextureScale;\n"
1314 " vec4 row1 = step(shadowmaptc.z, vec4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
1315 " vec4 row2 = step(shadowmaptc.z, vec4(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0), texval( 2.0, 0.0)));\n"
1316 " vec4 row3 = step(shadowmaptc.z, vec4(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0), texval( 2.0, 1.0)));\n"
1317 " vec4 row4 = step(shadowmaptc.z, vec4(texval(-1.0, 2.0), texval( 0.0, 2.0), texval( 1.0, 2.0), texval( 2.0, 2.0)));\n"
1318 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1319 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1321 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1322 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1323 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1324 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1325 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1326 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1330 " f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1333 "# ifdef USESHADOWMAPORTHO\n"
1334 " return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1340 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
1341 "#endif // FRAGMENT_SHADER\n"
1346 "#ifdef MODE_DEFERREDGEOMETRY\n"
1347 "#ifdef VERTEX_SHADER\n"
1348 "uniform highp mat4 TexMatrix;\n"
1349 "#ifdef USEVERTEXTEXTUREBLEND\n"
1350 "uniform highp mat4 BackgroundTexMatrix;\n"
1352 "uniform highp mat4 ModelViewMatrix;\n"
1355 " TexCoord = vec2(TexMatrix * Attrib_TexCoord0);\n"
1356 "#ifdef USEVERTEXTEXTUREBLEND\n"
1357 " VertexColor = Attrib_Color;\n"
1358 " TexCoord2 = vec2(BackgroundTexMatrix * Attrib_TexCoord0);\n"
1361 " // transform unnormalized eye direction into tangent space\n"
1362 "#ifdef USEOFFSETMAPPING\n"
1363 " vec3 EyeVectorModelSpace = EyePosition - Attrib_Position.xyz;\n"
1364 " EyeVector.x = dot(EyeVectorModelSpace, Attrib_TexCoord1.xyz);\n"
1365 " EyeVector.y = dot(EyeVectorModelSpace, Attrib_TexCoord2.xyz);\n"
1366 " EyeVector.z = dot(EyeVectorModelSpace, Attrib_TexCoord3.xyz);\n"
1369 " VectorS = (ModelViewMatrix * vec4(Attrib_TexCoord1.xyz, 0)).xyz;\n"
1370 " VectorT = (ModelViewMatrix * vec4(Attrib_TexCoord2.xyz, 0)).xyz;\n"
1371 " VectorR = (ModelViewMatrix * vec4(Attrib_TexCoord3.xyz, 0)).xyz;\n"
1372 " gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
1374 "#endif // VERTEX_SHADER\n"
1376 "#ifdef FRAGMENT_SHADER\n"
1379 "#ifdef USEOFFSETMAPPING\n"
1380 " // apply offsetmapping\n"
1381 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1382 "#define TexCoord TexCoordOffset\n"
1385 "#ifdef USEALPHAKILL\n"
1386 " if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1390 "#ifdef USEVERTEXTEXTUREBLEND\n"
1391 " float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1392 " float terrainblend = clamp(float(VertexColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1393 " //float terrainblend = min(float(VertexColor.a) * alpha * 2.0, float(1.0));\n"
1394 " //float terrainblend = float(VertexColor.a) * alpha > 0.5;\n"
1397 "#ifdef USEVERTEXTEXTUREBLEND\n"
1398 " vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1399 " float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
1401 " vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1402 " float a = texture2D(Texture_Gloss, TexCoord).a;\n"
1405 " gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
1407 "#endif // FRAGMENT_SHADER\n"
1408 "#else // !MODE_DEFERREDGEOMETRY\n"
1413 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1414 "#ifdef VERTEX_SHADER\n"
1415 "uniform highp mat4 ModelViewMatrix;\n"
1418 " ModelViewPosition = ModelViewMatrix * Attrib_Position;\n"
1419 " gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
1421 "#endif // VERTEX_SHADER\n"
1423 "#ifdef FRAGMENT_SHADER\n"
1424 "uniform highp mat4 ViewToLight;\n"
1425 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1426 "uniform highp vec2 ScreenToDepth;\n"
1427 "uniform myhalf3 DeferredColor_Ambient;\n"
1428 "uniform myhalf3 DeferredColor_Diffuse;\n"
1429 "#ifdef USESPECULAR\n"
1430 "uniform myhalf3 DeferredColor_Specular;\n"
1431 "uniform myhalf SpecularPower;\n"
1433 "uniform myhalf2 PixelToScreenTexCoord;\n"
1436 " // calculate viewspace pixel position\n"
1437 " vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1439 " position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1440 " position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1441 " // decode viewspace pixel normal\n"
1442 " myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1443 " myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1444 " // surfacenormal = pixel normal in viewspace\n"
1445 " // LightVector = pixel to light in viewspace\n"
1446 " // CubeVector = position in lightspace\n"
1447 " // eyevector = pixel to view in viewspace\n"
1448 " vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1449 " myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1450 "#ifdef USEDIFFUSE\n"
1451 " // calculate diffuse shading\n"
1452 " myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1453 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1455 "#ifdef USESPECULAR\n"
1456 " // calculate directional shading\n"
1457 " vec3 eyevector = position * -1.0;\n"
1458 "# ifdef USEEXACTSPECULARMATH\n"
1459 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
1461 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1462 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
1466 "#if defined(USESHADOWMAP2D)\n"
1467 " fade *= ShadowMapCompare(CubeVector);\n"
1470 "#ifdef USEDIFFUSE\n"
1471 " gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1473 " gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1475 "#ifdef USESPECULAR\n"
1476 " gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1478 " gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1481 "# ifdef USECUBEFILTER\n"
1482 " vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1483 " gl_FragData[0].rgb *= cubecolor;\n"
1484 " gl_FragData[1].rgb *= cubecolor;\n"
1487 "#endif // FRAGMENT_SHADER\n"
1488 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1493 "#ifdef VERTEX_SHADER\n"
1494 "uniform highp mat4 TexMatrix;\n"
1495 "#ifdef USEVERTEXTEXTUREBLEND\n"
1496 "uniform highp mat4 BackgroundTexMatrix;\n"
1498 "#ifdef MODE_LIGHTSOURCE\n"
1499 "uniform highp mat4 ModelToLight;\n"
1501 "#ifdef USESHADOWMAPORTHO\n"
1502 "uniform highp mat4 ShadowMapMatrix;\n"
1504 "#ifdef USEBOUNCEGRID\n"
1505 "uniform highp mat4 BounceGridMatrix;\n"
1509 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1510 " VertexColor = Attrib_Color;\n"
1512 " // copy the surface texcoord\n"
1513 " TexCoord = vec2(TexMatrix * Attrib_TexCoord0);\n"
1514 "#ifdef USEVERTEXTEXTUREBLEND\n"
1515 " TexCoord2 = vec2(BackgroundTexMatrix * Attrib_TexCoord0);\n"
1517 "#ifdef USELIGHTMAP\n"
1518 " TexCoordLightmap = vec2(Attrib_TexCoord4);\n"
1521 "#ifdef USEBOUNCEGRID\n"
1522 " BounceGridTexCoord = vec3(BounceGridMatrix * Attrib_Position);\n"
1525 "#ifdef MODE_LIGHTSOURCE\n"
1526 " // transform vertex position into light attenuation/cubemap space\n"
1527 " // (-1 to +1 across the light box)\n"
1528 " CubeVector = vec3(ModelToLight * Attrib_Position);\n"
1530 "# ifdef USEDIFFUSE\n"
1531 " // transform unnormalized light direction into tangent space\n"
1532 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
1533 " // normalize it per pixel)\n"
1534 " vec3 lightminusvertex = LightPosition - Attrib_Position.xyz;\n"
1535 " LightVector.x = dot(lightminusvertex, Attrib_TexCoord1.xyz);\n"
1536 " LightVector.y = dot(lightminusvertex, Attrib_TexCoord2.xyz);\n"
1537 " LightVector.z = dot(lightminusvertex, Attrib_TexCoord3.xyz);\n"
1541 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1542 " LightVector.x = dot(LightDir, Attrib_TexCoord1.xyz);\n"
1543 " LightVector.y = dot(LightDir, Attrib_TexCoord2.xyz);\n"
1544 " LightVector.z = dot(LightDir, Attrib_TexCoord3.xyz);\n"
1547 " // transform unnormalized eye direction into tangent space\n"
1548 "#ifdef USEEYEVECTOR\n"
1549 " vec3 EyeVectorModelSpace = EyePosition - Attrib_Position.xyz;\n"
1550 " EyeVector.x = dot(EyeVectorModelSpace, Attrib_TexCoord1.xyz);\n"
1551 " EyeVector.y = dot(EyeVectorModelSpace, Attrib_TexCoord2.xyz);\n"
1552 " EyeVector.z = dot(EyeVectorModelSpace, Attrib_TexCoord3.xyz);\n"
1556 " EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - Attrib_Position.xyz;\n"
1557 " EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, Attrib_Position);\n"
1560 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
1561 " VectorS = Attrib_TexCoord1.xyz;\n"
1562 " VectorT = Attrib_TexCoord2.xyz;\n"
1563 " VectorR = Attrib_TexCoord3.xyz;\n"
1566 " // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1567 " gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
1569 "#ifdef USESHADOWMAPORTHO\n"
1570 " ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
1573 "#ifdef USEREFLECTION\n"
1574 " ModelViewProjectionPosition = gl_Position;\n"
1577 "#endif // VERTEX_SHADER\n"
1582 "#ifdef FRAGMENT_SHADER\n"
1583 "#ifdef USEDEFERREDLIGHTMAP\n"
1584 "uniform myhalf2 PixelToScreenTexCoord;\n"
1585 "uniform myhalf3 DeferredMod_Diffuse;\n"
1586 "uniform myhalf3 DeferredMod_Specular;\n"
1588 "uniform myhalf3 Color_Ambient;\n"
1589 "uniform myhalf3 Color_Diffuse;\n"
1590 "uniform myhalf3 Color_Specular;\n"
1591 "uniform myhalf SpecularPower;\n"
1593 "uniform myhalf3 Color_Glow;\n"
1595 "uniform myhalf Alpha;\n"
1596 "#ifdef USEREFLECTION\n"
1597 "uniform mediump vec4 DistortScaleRefractReflect;\n"
1598 "uniform mediump vec4 ScreenScaleRefractReflect;\n"
1599 "uniform mediump vec4 ScreenCenterRefractReflect;\n"
1600 "uniform lowp vec4 ReflectColor;\n"
1602 "#ifdef USEREFLECTCUBE\n"
1603 "uniform highp mat4 ModelToReflectCube;\n"
1604 "uniform sampler2D Texture_ReflectMask;\n"
1605 "uniform samplerCube Texture_ReflectCube;\n"
1607 "#ifdef MODE_LIGHTDIRECTION\n"
1608 "uniform myhalf3 LightColor;\n"
1610 "#ifdef MODE_LIGHTSOURCE\n"
1611 "uniform myhalf3 LightColor;\n"
1613 "#ifdef USEBOUNCEGRID\n"
1614 "uniform sampler3D Texture_BounceGrid;\n"
1615 "uniform float BounceGridIntensity;\n"
1619 "#ifdef USEOFFSETMAPPING\n"
1620 " // apply offsetmapping\n"
1621 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1622 "#define TexCoord TexCoordOffset\n"
1625 " // combine the diffuse textures (base, pants, shirt)\n"
1626 " myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1627 "#ifdef USEALPHAKILL\n"
1628 " if (color.a < 0.5)\n"
1631 " color.a *= Alpha;\n"
1632 "#ifdef USECOLORMAPPING\n"
1633 " color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1635 "#ifdef USEVERTEXTEXTUREBLEND\n"
1636 " myhalf terrainblend = clamp(myhalf(VertexColor.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1637 " //myhalf terrainblend = min(myhalf(VertexColor.a) * color.a * 2.0, myhalf(1.0));\n"
1638 " //myhalf terrainblend = myhalf(VertexColor.a) * color.a > 0.5;\n"
1639 " color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1641 " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1644 " // get the surface normal\n"
1645 "#ifdef USEVERTEXTEXTUREBLEND\n"
1646 " myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1648 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1651 " // get the material colors\n"
1652 " myhalf3 diffusetex = color.rgb;\n"
1653 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1654 "# ifdef USEVERTEXTEXTUREBLEND\n"
1655 " myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1657 " myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
1661 "#ifdef USEREFLECTCUBE\n"
1662 " vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
1663 " vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
1664 " vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
1665 " diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
1671 "#ifdef MODE_LIGHTSOURCE\n"
1672 " // light source\n"
1673 "#ifdef USEDIFFUSE\n"
1674 " myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1675 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1676 " color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1677 "#ifdef USESPECULAR\n"
1678 "#ifdef USEEXACTSPECULARMATH\n"
1679 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1681 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1682 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1684 " color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
1687 " color.rgb = diffusetex * Color_Ambient;\n"
1689 " color.rgb *= LightColor;\n"
1690 " color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1691 "#if defined(USESHADOWMAP2D)\n"
1692 " color.rgb *= ShadowMapCompare(CubeVector);\n"
1694 "# ifdef USECUBEFILTER\n"
1695 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1697 "#endif // MODE_LIGHTSOURCE\n"
1702 "#ifdef MODE_LIGHTDIRECTION\n"
1704 "#ifdef USEDIFFUSE\n"
1705 " myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1707 "#define lightcolor LightColor\n"
1708 "#endif // MODE_LIGHTDIRECTION\n"
1709 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1711 " // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1712 " myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1713 " myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1714 " // convert modelspace light vector to tangentspace\n"
1715 " myhalf3 lightnormal;\n"
1716 " lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1717 " lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1718 " lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1719 " lightnormal = normalize(lightnormal); // VectorS/T/R are not always perfectly normalized, and EXACTSPECULARMATH is very picky about this\n"
1720 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1721 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1722 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1723 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1724 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1725 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1726 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1727 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1728 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1729 " lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1730 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1731 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1733 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1734 " myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1735 " myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1741 "#ifdef MODE_FAKELIGHT\n"
1743 "myhalf3 lightnormal = myhalf3(normalize(EyeVector));\n"
1744 "myhalf3 lightcolor = myhalf3(1.0);\n"
1745 "#endif // MODE_FAKELIGHT\n"
1750 "#ifdef MODE_LIGHTMAP\n"
1751 " color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1752 "#endif // MODE_LIGHTMAP\n"
1753 "#ifdef MODE_VERTEXCOLOR\n"
1754 " color.rgb = diffusetex * (Color_Ambient + myhalf3(VertexColor.rgb) * Color_Diffuse);\n"
1755 "#endif // MODE_VERTEXCOLOR\n"
1756 "#ifdef MODE_FLATCOLOR\n"
1757 " color.rgb = diffusetex * Color_Ambient;\n"
1758 "#endif // MODE_FLATCOLOR\n"
1764 "# ifdef USEDIFFUSE\n"
1765 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1766 "# ifdef USESPECULAR\n"
1767 "# ifdef USEEXACTSPECULARMATH\n"
1768 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1770 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1771 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1773 " color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
1775 " color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1778 " color.rgb = diffusetex * Color_Ambient;\n"
1782 "#ifdef USESHADOWMAPORTHO\n"
1783 " color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
1786 "#ifdef USEDEFERREDLIGHTMAP\n"
1787 " vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1788 " color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1789 " color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1792 "#ifdef USEBOUNCEGRID\n"
1793 " color.rgb += diffusetex * myhalf3(texture3D(Texture_BounceGrid, BounceGridTexCoord)) * BounceGridIntensity;\n"
1797 "#ifdef USEVERTEXTEXTUREBLEND\n"
1798 " color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1800 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1805 " color.rgb = FogVertex(color.rgb);\n"
1808 " // reflection must come last because it already contains exactly the correct fog (the reflection render preserves camera distance from the plane, it only flips the side) and ContrastBoost/SceneBrightness\n"
1809 "#ifdef USEREFLECTION\n"
1810 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1811 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1812 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1813 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1814 " // FIXME temporary hack to detect the case that the reflection\n"
1815 " // gets blackened at edges due to leaving the area that contains actual\n"
1817 " // Remove this 'ack once we have a better way to stop this thing from\n"
1819 " float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1820 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1821 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1822 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1823 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1824 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1827 " gl_FragColor = vec4(color);\n"
1829 "#endif // FRAGMENT_SHADER\n"
1831 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1832 "#endif // !MODE_DEFERREDGEOMETRY\n"
1833 "#endif // !MODE_WATER\n"
1834 "#endif // !MODE_REFRACTION\n"
1835 "#endif // !MODE_BLOOMBLUR\n"
1836 "#endif // !MODE_GENERIC\n"
1837 "#endif // !MODE_POSTPROCESS\n"
1838 "#endif // !MODE_SHOWDEPTH\n"
1839 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1843 =========================================================================================================================================================
1847 =========================================================================================================================================================
1851 =========================================================================================================================================================
1855 =========================================================================================================================================================
1859 =========================================================================================================================================================
1863 =========================================================================================================================================================
1867 =========================================================================================================================================================
1870 const char *builtinhlslshaderstring =
1871 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1872 "// written by Forest 'LordHavoc' Hale\n"
1873 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1875 "// FIXME: we need to get rid of ModelViewProjectionPosition to make room for the texcoord for this\n"
1876 "#if defined(USEREFLECTION)\n"
1877 "#undef USESHADOWMAPORTHO\n"
1880 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
1883 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1884 "#define USELIGHTMAP\n"
1886 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
1887 "#define USEEYEVECTOR\n"
1890 "#ifdef FRAGMENT_SHADER\n"
1892 "//#undef USESHADOWMAPPCF\n"
1893 "//#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1894 "#define texDepth2D(tex,texcoord) dot(tex2D(tex,texcoord).rgb, float3(1.0, 255.0/65536.0, 255.0/16777216.0))\n"
1896 "#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1900 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1901 "#ifdef VERTEX_SHADER\n"
1904 "float4 gl_Vertex : POSITION,\n"
1905 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1906 "out float4 gl_Position : POSITION,\n"
1907 "out float Depth : TEXCOORD0\n"
1910 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1911 " Depth = gl_Position.z;\n"
1915 "#ifdef FRAGMENT_SHADER\n"
1918 "float Depth : TEXCOORD0,\n"
1919 "out float4 gl_FragColor : COLOR\n"
1922 "// float4 temp = float4(Depth,Depth*(65536.0/255.0),Depth*(16777216.0/255.0),0.0);\n"
1923 " float4 temp = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
1924 " temp.yz -= floor(temp.yz);\n"
1925 " gl_FragColor = temp;\n"
1926 "// gl_FragColor = float4(Depth,0,0,0);\n"
1929 "#else // !MODE_DEPTH_ORSHADOW\n"
1934 "#ifdef MODE_SHOWDEPTH\n"
1935 "#ifdef VERTEX_SHADER\n"
1938 "float4 gl_Vertex : POSITION,\n"
1939 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1940 "out float4 gl_Position : POSITION,\n"
1941 "out float4 gl_FrontColor : COLOR0\n"
1944 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1945 " gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1949 "#ifdef FRAGMENT_SHADER\n"
1952 "float4 gl_FrontColor : COLOR0,\n"
1953 "out float4 gl_FragColor : COLOR\n"
1956 " gl_FragColor = gl_FrontColor;\n"
1959 "#else // !MODE_SHOWDEPTH\n"
1964 "#ifdef MODE_POSTPROCESS\n"
1966 "#ifdef VERTEX_SHADER\n"
1969 "float4 gl_Vertex : POSITION,\n"
1970 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1971 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1972 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
1973 "out float4 gl_Position : POSITION,\n"
1974 "out float2 TexCoord1 : TEXCOORD0,\n"
1975 "out float2 TexCoord2 : TEXCOORD1\n"
1978 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1979 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
1981 " TexCoord2 = gl_MultiTexCoord4.xy;\n"
1986 "#ifdef FRAGMENT_SHADER\n"
1989 "float2 TexCoord1 : TEXCOORD0,\n"
1990 "float2 TexCoord2 : TEXCOORD1,\n"
1991 "uniform sampler Texture_First : register(s0),\n"
1993 "uniform sampler Texture_Second : register(s1),\n"
1995 "#ifdef USEGAMMARAMPS\n"
1996 "uniform sampler Texture_GammaRamps : register(s2),\n"
1998 "#ifdef USESATURATION\n"
1999 "uniform float Saturation : register(c30),\n"
2001 "#ifdef USEVIEWTINT\n"
2002 "uniform float4 ViewTintColor : register(c41),\n"
2004 "uniform float4 UserVec1 : register(c37),\n"
2005 "uniform float4 UserVec2 : register(c38),\n"
2006 "uniform float4 UserVec3 : register(c39),\n"
2007 "uniform float4 UserVec4 : register(c40),\n"
2008 "uniform float ClientTime : register(c2),\n"
2009 "uniform float2 PixelSize : register(c25),\n"
2010 "uniform float4 BloomColorSubtract : register(c43),\n"
2011 "out float4 gl_FragColor : COLOR\n"
2014 " gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
2016 " gl_FragColor += max(float4(0,0,0,0), tex2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
2018 "#ifdef USEVIEWTINT\n"
2019 " gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
2022 "#ifdef USEPOSTPROCESSING\n"
2023 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
2024 "// this code does a blur with the radius specified in the first component of r_glsl_postprocess_uservec1 and blends it using the second component\n"
2025 " float sobel = 1.0;\n"
2026 " // float2 ts = textureSize(Texture_First, 0);\n"
2027 " // float2 px = float2(1/ts.x, 1/ts.y);\n"
2028 " float2 px = PixelSize;\n"
2029 " float3 x1 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
2030 " float3 x2 = tex2D(Texture_First, TexCoord1 + float2(-px.x, 0.0)).rgb;\n"
2031 " float3 x3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
2032 " float3 x4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
2033 " float3 x5 = tex2D(Texture_First, TexCoord1 + float2( px.x, 0.0)).rgb;\n"
2034 " float3 x6 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
2035 " float3 y1 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
2036 " float3 y2 = tex2D(Texture_First, TexCoord1 + float2( 0.0,-px.y)).rgb;\n"
2037 " float3 y3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
2038 " float3 y4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
2039 " float3 y5 = tex2D(Texture_First, TexCoord1 + float2( 0.0, px.y)).rgb;\n"
2040 " float3 y6 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
2041 " float px1 = -1.0 * dot(float3(0.3, 0.59, 0.11), x1);\n"
2042 " float px2 = -2.0 * dot(float3(0.3, 0.59, 0.11), x2);\n"
2043 " float px3 = -1.0 * dot(float3(0.3, 0.59, 0.11), x3);\n"
2044 " float px4 = 1.0 * dot(float3(0.3, 0.59, 0.11), x4);\n"
2045 " float px5 = 2.0 * dot(float3(0.3, 0.59, 0.11), x5);\n"
2046 " float px6 = 1.0 * dot(float3(0.3, 0.59, 0.11), x6);\n"
2047 " float py1 = -1.0 * dot(float3(0.3, 0.59, 0.11), y1);\n"
2048 " float py2 = -2.0 * dot(float3(0.3, 0.59, 0.11), y2);\n"
2049 " float py3 = -1.0 * dot(float3(0.3, 0.59, 0.11), y3);\n"
2050 " float py4 = 1.0 * dot(float3(0.3, 0.59, 0.11), y4);\n"
2051 " float py5 = 2.0 * dot(float3(0.3, 0.59, 0.11), y5);\n"
2052 " float py6 = 1.0 * dot(float3(0.3, 0.59, 0.11), y6);\n"
2053 " sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
2054 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
2055 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
2056 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
2057 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107, 0.707107)) * UserVec1.y;\n"
2058 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990, 0.891007)) * UserVec1.y;\n"
2059 " gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
2060 " gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + float3(1,1,1)*max(0.0, sobel - UserVec2.z)*UserVec2.y;\n"
2063 "#ifdef USESATURATION\n"
2064 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
2065 " float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
2066 " // 'vampire sight' effect, wheres red is compensated\n"
2067 " #ifdef SATURATION_REDCOMPENSATE\n"
2068 " float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n"
2069 " gl_FragColor.rgb = lerp(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2070 " gl_FragColor.r += r;\n"
2072 " // normal desaturation\n"
2073 " //gl_FragColor = float3(y,y,y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
2074 " gl_FragColor.rgb = lerp(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2078 "#ifdef USEGAMMARAMPS\n"
2079 " gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
2080 " gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
2081 " gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
2085 "#else // !MODE_POSTPROCESS\n"
2090 "#ifdef MODE_GENERIC\n"
2091 "#ifdef VERTEX_SHADER\n"
2094 "float4 gl_Vertex : POSITION,\n"
2095 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2096 "float4 gl_Color : COLOR0,\n"
2097 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2098 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2099 "out float4 gl_Position : POSITION,\n"
2100 "#ifdef USEDIFFUSE\n"
2101 "out float2 TexCoord1 : TEXCOORD0,\n"
2103 "#ifdef USESPECULAR\n"
2104 "out float2 TexCoord2 : TEXCOORD1,\n"
2106 "out float4 gl_FrontColor : COLOR\n"
2109 " gl_FrontColor = gl_Color;\n"
2110 "#ifdef USEDIFFUSE\n"
2111 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
2113 "#ifdef USESPECULAR\n"
2114 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
2116 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2120 "#ifdef FRAGMENT_SHADER\n"
2124 "float4 gl_FrontColor : COLOR0,\n"
2125 "float2 TexCoord1 : TEXCOORD0,\n"
2126 "float2 TexCoord2 : TEXCOORD1,\n"
2127 "#ifdef USEDIFFUSE\n"
2128 "uniform sampler Texture_First : register(s0),\n"
2130 "#ifdef USESPECULAR\n"
2131 "uniform sampler Texture_Second : register(s1),\n"
2133 "out float4 gl_FragColor : COLOR\n"
2136 "#ifdef USEVIEWTINT\n"
2137 " gl_FragColor = gl_FrontColor;\n"
2139 " gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
2141 "#ifdef USEDIFFUSE\n"
2142 " gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
2145 "#ifdef USESPECULAR\n"
2146 " float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
2147 "# ifdef USECOLORMAPPING\n"
2148 " gl_FragColor *= tex2;\n"
2151 " gl_FragColor += tex2;\n"
2153 "# ifdef USEVERTEXTEXTUREBLEND\n"
2154 " gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
2159 "#else // !MODE_GENERIC\n"
2164 "#ifdef MODE_BLOOMBLUR\n"
2165 "#ifdef VERTEX_SHADER\n"
2168 "float4 gl_Vertex : POSITION,\n"
2169 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2170 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2171 "out float4 gl_Position : POSITION,\n"
2172 "out float2 TexCoord : TEXCOORD0\n"
2175 " TexCoord = gl_MultiTexCoord0.xy;\n"
2176 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2180 "#ifdef FRAGMENT_SHADER\n"
2184 "float2 TexCoord : TEXCOORD0,\n"
2185 "uniform sampler Texture_First : register(s0),\n"
2186 "uniform float4 BloomBlur_Parameters : register(c1),\n"
2187 "out float4 gl_FragColor : COLOR\n"
2191 " float2 tc = TexCoord;\n"
2192 " float3 color = tex2D(Texture_First, tc).rgb;\n"
2193 " tc += BloomBlur_Parameters.xy;\n"
2194 " for (i = 1;i < SAMPLES;i++)\n"
2196 " color += tex2D(Texture_First, tc).rgb;\n"
2197 " tc += BloomBlur_Parameters.xy;\n"
2199 " gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
2202 "#else // !MODE_BLOOMBLUR\n"
2203 "#ifdef MODE_REFRACTION\n"
2204 "#ifdef VERTEX_SHADER\n"
2207 "float4 gl_Vertex : POSITION,\n"
2208 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2209 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2210 "uniform float4x4 TexMatrix : register(c0),\n"
2211 "uniform float3 EyePosition : register(c24),\n"
2212 "out float4 gl_Position : POSITION,\n"
2213 "out float2 TexCoord : TEXCOORD0,\n"
2214 "out float3 EyeVector : TEXCOORD1,\n"
2215 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2218 " TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2219 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2220 " ModelViewProjectionPosition = gl_Position;\n"
2224 "#ifdef FRAGMENT_SHADER\n"
2227 "float2 TexCoord : TEXCOORD0,\n"
2228 "float3 EyeVector : TEXCOORD1,\n"
2229 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2230 "uniform sampler Texture_Normal : register(s0),\n"
2231 "uniform sampler Texture_Refraction : register(s3),\n"
2232 "uniform sampler Texture_Reflection : register(s7),\n"
2233 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2234 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2235 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2236 "uniform float4 RefractColor : register(c29),\n"
2237 "out float4 gl_FragColor : COLOR\n"
2240 " float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2241 " //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"
2242 " float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2243 " float2 ScreenTexCoord = SafeScreenTexCoord + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy * DistortScaleRefractReflect.xy;\n"
2244 " // FIXME temporary hack to detect the case that the reflection\n"
2245 " // gets blackened at edges due to leaving the area that contains actual\n"
2247 " // Remove this 'ack once we have a better way to stop this thing from\n"
2249 " float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2250 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2251 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2252 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2253 " ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2254 " gl_FragColor = float4(tex2D(Texture_Refraction, ScreenTexCoord).rgb, 1) * RefractColor;\n"
2257 "#else // !MODE_REFRACTION\n"
2262 "#ifdef MODE_WATER\n"
2263 "#ifdef VERTEX_SHADER\n"
2267 "float4 gl_Vertex : POSITION,\n"
2268 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2269 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2270 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2271 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2272 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2273 "uniform float4x4 TexMatrix : register(c0),\n"
2274 "uniform float3 EyePosition : register(c24),\n"
2275 "out float4 gl_Position : POSITION,\n"
2276 "out float2 TexCoord : TEXCOORD0,\n"
2277 "out float3 EyeVector : TEXCOORD1,\n"
2278 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2281 " TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2282 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2283 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2284 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2285 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2286 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2287 " ModelViewProjectionPosition = gl_Position;\n"
2291 "#ifdef FRAGMENT_SHADER\n"
2294 "float2 TexCoord : TEXCOORD0,\n"
2295 "float3 EyeVector : TEXCOORD1,\n"
2296 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2297 "uniform sampler Texture_Normal : register(s0),\n"
2298 "uniform sampler Texture_Refraction : register(s3),\n"
2299 "uniform sampler Texture_Reflection : register(s7),\n"
2300 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2301 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2302 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2303 "uniform float4 RefractColor : register(c29),\n"
2304 "uniform float4 ReflectColor : register(c26),\n"
2305 "uniform float ReflectFactor : register(c27),\n"
2306 "uniform float ReflectOffset : register(c28),\n"
2307 "out float4 gl_FragColor : COLOR\n"
2310 " float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2311 " //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2312 " float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2313 " //SafeScreenTexCoord = gl_FragCoord.xyxy * float4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
2314 " float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy).xyxy * DistortScaleRefractReflect;\n"
2315 " // FIXME temporary hack to detect the case that the reflection\n"
2316 " // gets blackened at edges due to leaving the area that contains actual\n"
2318 " // Remove this 'ack once we have a better way to stop this thing from\n"
2320 " float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2321 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2322 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2323 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2324 " ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2325 " f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2326 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2327 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2328 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2329 " ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2330 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2331 " gl_FragColor = lerp(float4(tex2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, float4(tex2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
2334 "#else // !MODE_WATER\n"
2339 "// 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"
2341 "// fragment shader specific:\n"
2342 "#ifdef FRAGMENT_SHADER\n"
2345 "float3 FogVertex(float3 surfacecolor, float3 FogColor, float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler Texture_FogMask, sampler Texture_FogHeightTexture)\n"
2348 "#ifdef USEFOGHEIGHTTEXTURE\n"
2349 " float4 fogheightpixel = tex2D(Texture_FogHeightTexture, float2(1,1) + float2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
2350 " fogfrac = fogheightpixel.a;\n"
2351 " return lerp(fogheightpixel.rgb * FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2353 "# ifdef USEFOGOUTSIDE\n"
2354 " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2356 " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2358 " return lerp(FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2363 "#ifdef USEOFFSETMAPPING\n"
2364 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler Texture_Normal)\n"
2366 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2367 " // 14 sample relief mapping: linear search and then binary search\n"
2368 " // this basically steps forward a small amount repeatedly until it finds\n"
2369 " // itself inside solid, then jitters forward and back using decreasing\n"
2370 " // amounts to find the impact\n"
2371 " //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2372 " //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2373 " float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2374 " float3 RT = float3(TexCoord, 1);\n"
2375 " OffsetVector *= 0.1;\n"
2376 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2377 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2378 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2379 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2380 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2381 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2382 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2383 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2384 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2385 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
2386 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
2387 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
2388 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
2389 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2392 " // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2393 " //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2394 " //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2395 " float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2396 " OffsetVector *= 0.5;\n"
2397 " TexCoord += OffsetVector * (1.0 - tex2D(Texture_Normal, TexCoord).a);\n"
2398 " TexCoord += OffsetVector * (1.0 - tex2D(Texture_Normal, TexCoord).a);\n"
2399 " return TexCoord;\n"
2402 "#endif // USEOFFSETMAPPING\n"
2404 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2405 "#if defined(USESHADOWMAP2D)\n"
2406 "# ifdef USESHADOWMAPORTHO\n"
2407 "# define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n"
2409 "# ifdef USESHADOWMAPVSDCT\n"
2410 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2412 " float3 adir = abs(dir);\n"
2413 " float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
2414 " float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2415 " return float3(lerp(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2418 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2420 " float3 adir = abs(dir);\n"
2421 " float ma = adir.z;\n"
2422 " float4 proj = float4(dir, 2.5);\n"
2423 " if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
2424 " if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
2426 " 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"
2428 " float2 aparams = ShadowMap_Parameters.xy / ma;\n"
2429 " 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"
2434 "#endif // defined(USESHADOWMAP2D)\n"
2436 "# ifdef USESHADOWMAP2D\n"
2437 "#ifdef USESHADOWMAPVSDCT\n"
2438 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2440 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2443 "#ifdef USESHADOWMAPVSDCT\n"
2444 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2446 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2450 "# ifdef USESHADOWSAMPLER\n"
2451 "# ifdef USESHADOWMAPPCF\n"
2452 "# define texval(x, y) tex2Dproj(Texture_ShadowMap2D, float4(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r \n"
2453 " float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2454 " 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"
2456 " f = tex2Dproj(Texture_ShadowMap2D, float4(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r;\n"
2459 "# ifdef USESHADOWMAPPCF\n"
2460 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2461 "# ifdef GL_ARB_texture_gather\n"
2462 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, int2(x, y))\n"
2464 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)\n"
2466 " float2 offset = frac(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
2467 "# if USESHADOWMAPPCF > 1\n"
2468 " float4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
2469 " float4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
2470 " float4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
2471 " float4 group4 = step(shadowmaptc.z, texval(-2.0, 0.0));\n"
2472 " float4 group5 = step(shadowmaptc.z, texval( 0.0, 0.0));\n"
2473 " float4 group6 = step(shadowmaptc.z, texval( 2.0, 0.0));\n"
2474 " float4 group7 = step(shadowmaptc.z, texval(-2.0, 2.0));\n"
2475 " float4 group8 = step(shadowmaptc.z, texval( 0.0, 2.0));\n"
2476 " float4 group9 = step(shadowmaptc.z, texval( 2.0, 2.0));\n"
2477 " float4 locols = float4(group1.ab, group3.ab);\n"
2478 " float4 hicols = float4(group7.rg, group9.rg);\n"
2479 " locols.yz += group2.ab;\n"
2480 " hicols.yz += group8.rg;\n"
2481 " float4 midcols = float4(group1.rg, group3.rg) + float4(group7.ab, group9.ab) +\n"
2482 " float4(group4.rg, group6.rg) + float4(group4.ab, group6.ab) +\n"
2483 " lerp(locols, hicols, offset.y);\n"
2484 " float4 cols = group5 + float4(group2.rg, group8.ab);\n"
2485 " cols.xyz += lerp(midcols.xyz, midcols.yzw, offset.x);\n"
2486 " f = dot(cols, float4(1.0/25.0));\n"
2488 " float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2489 " float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2490 " float4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
2491 " float4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
2492 " float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2493 " lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2494 " f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2497 "# ifdef GL_EXT_gpu_shader4\n"
2498 "# define texval(x, y) tex2DOffset(Texture_ShadowMap2D, center, int2(x, y)).r\n"
2500 "# define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale).r \n"
2502 "# if USESHADOWMAPPCF > 1\n"
2503 " float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2504 " center *= ShadowMap_TextureScale;\n"
2505 " 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"
2506 " 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"
2507 " 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"
2508 " 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"
2509 " float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2510 " f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2512 " float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2513 " float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2514 " float3 row2 = step(shadowmaptc.z, float3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
2515 " float3 row3 = step(shadowmaptc.z, float3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
2516 " float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2517 " f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25,0.25));\n"
2521 " f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2524 "# ifdef USESHADOWMAPORTHO\n"
2525 " return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2531 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
2532 "#endif // FRAGMENT_SHADER\n"
2537 "#ifdef MODE_DEFERREDGEOMETRY\n"
2538 "#ifdef VERTEX_SHADER\n"
2541 "float4 gl_Vertex : POSITION,\n"
2542 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2543 "#ifdef USEVERTEXTEXTUREBLEND\n"
2544 "float4 gl_Color : COLOR0,\n"
2546 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2547 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2548 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2549 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2550 "uniform float4x4 TexMatrix : register(c0),\n"
2551 "#ifdef USEVERTEXTEXTUREBLEND\n"
2552 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2554 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2555 "#ifdef USEOFFSETMAPPING\n"
2556 "uniform float3 EyePosition : register(c24),\n"
2558 "out float4 gl_Position : POSITION,\n"
2559 "#ifdef USEVERTEXTEXTUREBLEND\n"
2560 "out float4 gl_FrontColor : COLOR,\n"
2562 "out float4 TexCoordBoth : TEXCOORD0,\n"
2563 "#ifdef USEOFFSETMAPPING\n"
2564 "out float3 EyeVector : TEXCOORD2,\n"
2566 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2567 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2568 "out float4 VectorR : TEXCOORD7 // direction of R texcoord (surface normal), Depth value\n"
2571 " TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2572 "#ifdef USEVERTEXTEXTUREBLEND\n"
2573 " gl_FrontColor = gl_Color;\n"
2574 " TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2577 " // transform unnormalized eye direction into tangent space\n"
2578 "#ifdef USEOFFSETMAPPING\n"
2579 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2580 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2581 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2582 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2585 " VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2586 " VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2587 " VectorR.xyz = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2588 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2589 " VectorR.w = gl_Position.z;\n"
2591 "#endif // VERTEX_SHADER\n"
2593 "#ifdef FRAGMENT_SHADER\n"
2596 "float4 TexCoordBoth : TEXCOORD0,\n"
2597 "float3 EyeVector : TEXCOORD2,\n"
2598 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2599 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2600 "float4 VectorR : TEXCOORD7, // direction of R texcoord (surface normal), Depth value\n"
2601 "uniform sampler Texture_Normal : register(s0),\n"
2602 "#ifdef USEALPHAKILL\n"
2603 "uniform sampler Texture_Color : register(s1),\n"
2605 "uniform sampler Texture_Gloss : register(s2),\n"
2606 "#ifdef USEVERTEXTEXTUREBLEND\n"
2607 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2608 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2610 "#ifdef USEOFFSETMAPPING\n"
2611 "uniform float OffsetMapping_Scale : register(c24),\n"
2613 "uniform half SpecularPower : register(c36),\n"
2615 "out float4 gl_FragData0 : COLOR0,\n"
2616 "out float4 gl_FragData1 : COLOR1\n"
2618 "out float4 gl_FragColor : COLOR\n"
2622 " float2 TexCoord = TexCoordBoth.xy;\n"
2623 "#ifdef USEOFFSETMAPPING\n"
2624 " // apply offsetmapping\n"
2625 " float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2626 "#define TexCoord TexCoordOffset\n"
2629 "#ifdef USEALPHAKILL\n"
2630 " if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2634 "#ifdef USEVERTEXTEXTUREBLEND\n"
2635 " float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2636 " float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2637 " //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2638 " //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2641 "#ifdef USEVERTEXTEXTUREBLEND\n"
2642 " float3 surfacenormal = lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend) - float3(0.5, 0.5, 0.5);\n"
2643 " float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2).a, tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
2645 " float3 surfacenormal = tex2D(Texture_Normal, TexCoord).rgb - float3(0.5, 0.5, 0.5);\n"
2646 " float a = tex2D(Texture_Gloss, TexCoord).a;\n"
2650 " 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"
2651 " float Depth = VectorR.w / 256.0;\n"
2652 " float4 depthcolor = float4(Depth,Depth*65536.0/255.0,Depth*16777216.0/255.0,0.0);\n"
2653 "// float4 depthcolor = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
2654 " depthcolor.yz -= floor(depthcolor.yz);\n"
2655 " gl_FragData1 = depthcolor;\n"
2657 " gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), a);\n"
2660 "#endif // FRAGMENT_SHADER\n"
2661 "#else // !MODE_DEFERREDGEOMETRY\n"
2666 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2667 "#ifdef VERTEX_SHADER\n"
2670 "float4 gl_Vertex : POSITION,\n"
2671 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2672 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2673 "out float4 gl_Position : POSITION,\n"
2674 "out float4 ModelViewPosition : TEXCOORD0\n"
2677 " ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2678 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2680 "#endif // VERTEX_SHADER\n"
2682 "#ifdef FRAGMENT_SHADER\n"
2686 "float2 Pixel : VPOS,\n"
2688 "float2 Pixel : WPOS,\n"
2690 "float4 ModelViewPosition : TEXCOORD0,\n"
2691 "uniform float4x4 ViewToLight : register(c44),\n"
2692 "uniform float2 ScreenToDepth : register(c33), // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2693 "uniform float3 LightPosition : register(c23),\n"
2694 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
2695 "uniform half3 DeferredColor_Ambient : register(c9),\n"
2696 "uniform half3 DeferredColor_Diffuse : register(c10),\n"
2697 "#ifdef USESPECULAR\n"
2698 "uniform half3 DeferredColor_Specular : register(c11),\n"
2699 "uniform half SpecularPower : register(c36),\n"
2701 "uniform sampler Texture_Attenuation : register(s9),\n"
2702 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2703 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2705 "#ifdef USECUBEFILTER\n"
2706 "uniform samplerCUBE Texture_Cube : register(s10),\n"
2709 "#ifdef USESHADOWMAP2D\n"
2710 "# ifdef USESHADOWSAMPLER\n"
2711 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2713 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2717 "#ifdef USESHADOWMAPVSDCT\n"
2718 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
2721 "#if defined(USESHADOWMAP2D)\n"
2722 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
2723 "uniform float4 ShadowMap_Parameters : register(c34),\n"
2726 "out float4 gl_FragData0 : COLOR0,\n"
2727 "out float4 gl_FragData1 : COLOR1\n"
2730 " // calculate viewspace pixel position\n"
2731 " float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2732 " //ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2733 " float3 position;\n"
2735 " position.z = texDepth2D(Texture_ScreenDepth, ScreenTexCoord) * 256.0;\n"
2737 " position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2739 " position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2740 " // decode viewspace pixel normal\n"
2741 " half4 normalmap = half4(tex2D(Texture_ScreenNormalMap, ScreenTexCoord));\n"
2742 " half3 surfacenormal = half3(normalize(normalmap.rgb - half3(0.5,0.5,0.5)));\n"
2743 " // surfacenormal = pixel normal in viewspace\n"
2744 " // LightVector = pixel to light in viewspace\n"
2745 " // CubeVector = position in lightspace\n"
2746 " // eyevector = pixel to view in viewspace\n"
2747 " float3 CubeVector = mul(ViewToLight, float4(position,1)).xyz;\n"
2748 " half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
2749 "#ifdef USEDIFFUSE\n"
2750 " // calculate diffuse shading\n"
2751 " half3 lightnormal = half3(normalize(LightPosition - position));\n"
2752 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2754 "#ifdef USESPECULAR\n"
2755 " // calculate directional shading\n"
2756 " float3 eyevector = position * -1.0;\n"
2757 "# ifdef USEEXACTSPECULARMATH\n"
2758 " half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a));\n"
2760 " half3 specularnormal = half3(normalize(lightnormal + half3(normalize(eyevector))));\n"
2761 " half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a));\n"
2765 "#if defined(USESHADOWMAP2D)\n"
2766 " fade *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2767 "#ifdef USESHADOWMAPVSDCT\n"
2768 ", Texture_CubeProjection\n"
2773 "#ifdef USEDIFFUSE\n"
2774 " gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2776 " gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2778 "#ifdef USESPECULAR\n"
2779 " gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2781 " gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2784 "# ifdef USECUBEFILTER\n"
2785 " float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2786 " gl_FragData0.rgb *= cubecolor;\n"
2787 " gl_FragData1.rgb *= cubecolor;\n"
2790 "#endif // FRAGMENT_SHADER\n"
2791 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2796 "#ifdef VERTEX_SHADER\n"
2799 "float4 gl_Vertex : POSITION,\n"
2800 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2801 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2802 "float4 gl_Color : COLOR0,\n"
2804 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2805 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2806 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2807 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2808 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2810 "uniform float3 EyePosition : register(c24),\n"
2811 "uniform float4x4 TexMatrix : register(c0),\n"
2812 "#ifdef USEVERTEXTEXTUREBLEND\n"
2813 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2815 "#ifdef MODE_LIGHTSOURCE\n"
2816 "uniform float4x4 ModelToLight : register(c20),\n"
2818 "#ifdef MODE_LIGHTSOURCE\n"
2819 "uniform float3 LightPosition : register(c27),\n"
2821 "#ifdef MODE_LIGHTDIRECTION\n"
2822 "uniform float3 LightDir : register(c26),\n"
2824 "uniform float4 FogPlane : register(c25),\n"
2825 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2826 "uniform float3 LightPosition : register(c27),\n"
2828 "#ifdef USESHADOWMAPORTHO\n"
2829 "uniform float4x4 ShadowMapMatrix : register(c16),\n"
2831 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2832 "out float4 gl_FrontColor : COLOR,\n"
2834 "out float4 TexCoordBoth : TEXCOORD0,\n"
2835 "#ifdef USELIGHTMAP\n"
2836 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2838 "#ifdef USEEYEVECTOR\n"
2839 "out float3 EyeVector : TEXCOORD2,\n"
2841 "#ifdef USEREFLECTION\n"
2842 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2845 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2847 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE) || defined(USEDIFFUSE)\n"
2848 "out float3 LightVector : TEXCOORD1,\n"
2850 "#ifdef MODE_LIGHTSOURCE\n"
2851 "out float3 CubeVector : TEXCOORD3,\n"
2853 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2854 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2855 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2856 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2858 "#ifdef USESHADOWMAPORTHO\n"
2859 "out float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2861 "out float4 gl_Position : POSITION\n"
2864 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2865 " gl_FrontColor = gl_Color;\n"
2867 " // copy the surface texcoord\n"
2868 " TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2869 "#ifdef USEVERTEXTEXTUREBLEND\n"
2870 " TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2872 "#ifdef USELIGHTMAP\n"
2873 " TexCoordLightmap = gl_MultiTexCoord4.xy;\n"
2876 "#ifdef MODE_LIGHTSOURCE\n"
2877 " // transform vertex position into light attenuation/cubemap space\n"
2878 " // (-1 to +1 across the light box)\n"
2879 " CubeVector = mul(ModelToLight, gl_Vertex).xyz;\n"
2881 "# ifdef USEDIFFUSE\n"
2882 " // transform unnormalized light direction into tangent space\n"
2883 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
2884 " // normalize it per pixel)\n"
2885 " float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2886 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2887 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2888 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2892 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2893 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2894 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2895 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2898 " // transform unnormalized eye direction into tangent space\n"
2899 "#ifdef USEEYEVECTOR\n"
2900 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2901 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2902 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2903 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2907 " EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2908 " EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2911 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2912 " VectorS = gl_MultiTexCoord1.xyz;\n"
2913 " VectorT = gl_MultiTexCoord2.xyz;\n"
2914 " VectorR = gl_MultiTexCoord3.xyz;\n"
2917 " // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2918 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2920 "#ifdef USESHADOWMAPORTHO\n"
2921 " ShadowMapTC = mul(ShadowMapMatrix, gl_Position).xyz;\n"
2924 "#ifdef USEREFLECTION\n"
2925 " ModelViewProjectionPosition = gl_Position;\n"
2928 "#endif // VERTEX_SHADER\n"
2933 "#ifdef FRAGMENT_SHADER\n"
2936 "#ifdef USEDEFERREDLIGHTMAP\n"
2938 "float2 Pixel : VPOS,\n"
2940 "float2 Pixel : WPOS,\n"
2943 "float4 gl_FrontColor : COLOR,\n"
2944 "float4 TexCoordBoth : TEXCOORD0,\n"
2945 "#ifdef USELIGHTMAP\n"
2946 "float2 TexCoordLightmap : TEXCOORD1,\n"
2948 "#ifdef USEEYEVECTOR\n"
2949 "float3 EyeVector : TEXCOORD2,\n"
2951 "#ifdef USEREFLECTION\n"
2952 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2955 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2957 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2958 "float3 LightVector : TEXCOORD1,\n"
2960 "#ifdef MODE_LIGHTSOURCE\n"
2961 "float3 CubeVector : TEXCOORD3,\n"
2963 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2964 "float4 ModelViewPosition : TEXCOORD0,\n"
2966 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2967 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2968 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2969 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2971 "#ifdef USESHADOWMAPORTHO\n"
2972 "float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2975 "uniform sampler Texture_Normal : register(s0),\n"
2976 "uniform sampler Texture_Color : register(s1),\n"
2977 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2978 "uniform sampler Texture_Gloss : register(s2),\n"
2981 "uniform sampler Texture_Glow : register(s3),\n"
2983 "#ifdef USEVERTEXTEXTUREBLEND\n"
2984 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2985 "uniform sampler Texture_SecondaryColor : register(s5),\n"
2986 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2987 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2990 "uniform sampler Texture_SecondaryGlow : register(s7),\n"
2993 "#ifdef USECOLORMAPPING\n"
2994 "uniform sampler Texture_Pants : register(s4),\n"
2995 "uniform sampler Texture_Shirt : register(s7),\n"
2998 "uniform sampler Texture_FogHeightTexture : register(s14),\n"
2999 "uniform sampler Texture_FogMask : register(s8),\n"
3001 "#ifdef USELIGHTMAP\n"
3002 "uniform sampler Texture_Lightmap : register(s9),\n"
3004 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
3005 "uniform sampler Texture_Deluxemap : register(s10),\n"
3007 "#ifdef USEREFLECTION\n"
3008 "uniform sampler Texture_Reflection : register(s7),\n"
3011 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
3012 "uniform sampler Texture_ScreenDepth : register(s13),\n"
3013 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
3015 "#ifdef USEDEFERREDLIGHTMAP\n"
3016 "uniform sampler Texture_ScreenDepth : register(s13),\n"
3017 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
3018 "uniform sampler Texture_ScreenDiffuse : register(s11),\n"
3019 "uniform sampler Texture_ScreenSpecular : register(s12),\n"
3022 "#ifdef USECOLORMAPPING\n"
3023 "uniform half3 Color_Pants : register(c7),\n"
3024 "uniform half3 Color_Shirt : register(c8),\n"
3027 "uniform float3 FogColor : register(c16),\n"
3028 "uniform float FogRangeRecip : register(c20),\n"
3029 "uniform float FogPlaneViewDist : register(c19),\n"
3030 "uniform float FogHeightFade : register(c17),\n"
3033 "#ifdef USEOFFSETMAPPING\n"
3034 "uniform float OffsetMapping_Scale : register(c24),\n"
3037 "#ifdef USEDEFERREDLIGHTMAP\n"
3038 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
3039 "uniform half3 DeferredMod_Diffuse : register(c12),\n"
3040 "uniform half3 DeferredMod_Specular : register(c13),\n"
3042 "uniform half3 Color_Ambient : register(c3),\n"
3043 "uniform half3 Color_Diffuse : register(c4),\n"
3044 "uniform half3 Color_Specular : register(c5),\n"
3045 "uniform half SpecularPower : register(c36),\n"
3047 "uniform half3 Color_Glow : register(c6),\n"
3049 "uniform half Alpha : register(c0),\n"
3050 "#ifdef USEREFLECTION\n"
3051 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
3052 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
3053 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
3054 "uniform half4 ReflectColor : register(c26),\n"
3056 "#ifdef USEREFLECTCUBE\n"
3057 "uniform float4x4 ModelToReflectCube : register(c48),\n"
3058 "uniform sampler Texture_ReflectMask : register(s5),\n"
3059 "uniform samplerCUBE Texture_ReflectCube : register(s6),\n"
3061 "#ifdef MODE_LIGHTDIRECTION\n"
3062 "uniform half3 LightColor : register(c21),\n"
3064 "#ifdef MODE_LIGHTSOURCE\n"
3065 "uniform half3 LightColor : register(c21),\n"
3068 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
3069 "uniform sampler Texture_Attenuation : register(s9),\n"
3070 "uniform samplerCUBE Texture_Cube : register(s10),\n"
3073 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
3075 "#ifdef USESHADOWMAP2D\n"
3076 "# ifdef USESHADOWSAMPLER\n"
3077 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
3079 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
3083 "#ifdef USESHADOWMAPVSDCT\n"
3084 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
3087 "#if defined(USESHADOWMAP2D)\n"
3088 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
3089 "uniform float4 ShadowMap_Parameters : register(c34),\n"
3091 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
3093 "out float4 gl_FragColor : COLOR\n"
3096 " float2 TexCoord = TexCoordBoth.xy;\n"
3097 "#ifdef USEVERTEXTEXTUREBLEND\n"
3098 " float2 TexCoord2 = TexCoordBoth.zw;\n"
3100 "#ifdef USEOFFSETMAPPING\n"
3101 " // apply offsetmapping\n"
3102 " float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
3103 "#define TexCoord TexCoordOffset\n"
3106 " // combine the diffuse textures (base, pants, shirt)\n"
3107 " half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
3108 "#ifdef USEALPHAKILL\n"
3109 " if (color.a < 0.5)\n"
3112 " color.a *= Alpha;\n"
3113 "#ifdef USECOLORMAPPING\n"
3114 " color.rgb += half3(tex2D(Texture_Pants, TexCoord).rgb) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord).rgb) * Color_Shirt;\n"
3116 "#ifdef USEVERTEXTEXTUREBLEND\n"
3117 " half terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
3118 " //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
3119 " //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
3120 " color.rgb = half3(lerp(tex2D(Texture_SecondaryColor, TexCoord2).rgb, float3(color.rgb), terrainblend));\n"
3122 " //color = half4(lerp(float4(1, 0, 0, 1), color, terrainblend));\n"
3125 " // get the surface normal\n"
3126 "#ifdef USEVERTEXTEXTUREBLEND\n"
3127 " half3 surfacenormal = normalize(half3(lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend)) - half3(0.5, 0.5, 0.5));\n"
3129 " half3 surfacenormal = half3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5, 0.5, 0.5)));\n"
3132 " // get the material colors\n"
3133 " half3 diffusetex = color.rgb;\n"
3134 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3135 "# ifdef USEVERTEXTEXTUREBLEND\n"
3136 " half4 glosstex = half4(lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord), terrainblend));\n"
3138 " half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
3142 "#ifdef USEREFLECTCUBE\n"
3143 " float3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
3144 " float3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
3145 " float3 ReflectCubeTexCoord = mul(ModelToReflectCube, float4(ModelReflectVector, 0)).xyz;\n"
3146 " diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord).rgb) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord).rgb);\n"
3152 "#ifdef MODE_LIGHTSOURCE\n"
3153 " // light source\n"
3154 "#ifdef USEDIFFUSE\n"
3155 " half3 lightnormal = half3(normalize(LightVector));\n"
3156 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3157 " color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
3158 "#ifdef USESPECULAR\n"
3159 "#ifdef USEEXACTSPECULARMATH\n"
3160 " half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3162 " half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3163 " half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3165 " color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
3168 " color.rgb = diffusetex * Color_Ambient;\n"
3170 " color.rgb *= LightColor;\n"
3171 " color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
3172 "#if defined(USESHADOWMAP2D)\n"
3173 " color.rgb *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3174 "#ifdef USESHADOWMAPVSDCT\n"
3175 ", Texture_CubeProjection\n"
3180 "# ifdef USECUBEFILTER\n"
3181 " color.rgb *= half3(texCUBE(Texture_Cube, CubeVector).rgb);\n"
3184 "#ifdef USESHADOWMAP2D\n"
3185 "#ifdef USESHADOWMAPVSDCT\n"
3186 "// float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters, Texture_CubeProjection);\n"
3188 "// float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters);\n"
3190 "// color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3191 "// color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3192 "// color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3193 "// color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3194 "// color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3195 "// color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3196 "// color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3197 "// color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3198 "// color.r = half(shadowmaptc.z - texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3199 "// color.r = half(shadowmaptc.z);\n"
3200 "// color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3201 "// color.r = half(shadowmaptc.z);\n"
3203 "// color.rgb = abs(CubeVector);\n"
3205 "// color.rgb = half3(1,1,1);\n"
3206 "#endif // MODE_LIGHTSOURCE\n"
3211 "#ifdef MODE_LIGHTDIRECTION\n"
3213 "#ifdef USEDIFFUSE\n"
3214 " half3 lightnormal = half3(normalize(LightVector));\n"
3216 "#define lightcolor LightColor\n"
3217 "#endif // MODE_LIGHTDIRECTION\n"
3218 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3220 " // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3221 " half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3222 " half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3223 " // convert modelspace light vector to tangentspace\n"
3224 " half3 lightnormal;\n"
3225 " lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3226 " lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3227 " lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3228 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3229 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3230 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3231 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3232 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3233 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3234 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3235 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3236 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3237 " lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3238 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3239 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3241 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3242 " half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3243 " half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3249 "#ifdef MODE_FAKELIGHT\n"
3251 "half3 lightnormal = half3(normalize(EyeVector));\n"
3252 "half3 lightcolor = half3(1.0,1.0,1.0);\n"
3253 "#endif // MODE_FAKELIGHT\n"
3258 "#ifdef MODE_LIGHTMAP\n"
3259 " color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb) * Color_Diffuse);\n"
3260 "#endif // MODE_LIGHTMAP\n"
3261 "#ifdef MODE_VERTEXCOLOR\n"
3262 " color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3263 "#endif // MODE_VERTEXCOLOR\n"
3264 "#ifdef MODE_FLATCOLOR\n"
3265 " color.rgb = diffusetex * Color_Ambient;\n"
3266 "#endif // MODE_FLATCOLOR\n"
3272 "# ifdef USEDIFFUSE\n"
3273 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3274 "# ifdef USESPECULAR\n"
3275 "# ifdef USEEXACTSPECULARMATH\n"
3276 " half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3278 " half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3279 " half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3281 " color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3283 " color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3286 " color.rgb = diffusetex * Color_Ambient;\n"
3290 "#ifdef USESHADOWMAPORTHO\n"
3291 " color.rgb *= half(ShadowMapCompare(ShadowMapTC, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale));\n"
3294 "#ifdef USEDEFERREDLIGHTMAP\n"
3295 " float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3296 " color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord).rgb) * DeferredMod_Diffuse;\n"
3297 " color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord).rgb) * DeferredMod_Specular;\n"
3298 "// color.rgb = half3(tex2D(Texture_ScreenDepth, ScreenTexCoord).rgb);\n"
3299 "// color.r = half(texDepth2D(Texture_ScreenDepth, ScreenTexCoord)) * 1.0;\n"
3303 "#ifdef USEVERTEXTEXTUREBLEND\n"
3304 " color.rgb += half3(lerp(tex2D(Texture_SecondaryGlow, TexCoord2).rgb, tex2D(Texture_Glow, TexCoord).rgb, terrainblend)) * Color_Glow;\n"
3306 " color.rgb += half3(tex2D(Texture_Glow, TexCoord).rgb) * Color_Glow;\n"
3311 " color.rgb = FogVertex(color.rgb, FogColor, EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask, Texture_FogHeightTexture);\n"
3314 " // 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"
3315 "#ifdef USEREFLECTION\n"
3316 " float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3317 " //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3318 " float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3319 " float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.zw;\n"
3320 " // FIXME temporary hack to detect the case that the reflection\n"
3321 " // gets blackened at edges due to leaving the area that contains actual\n"
3323 " // Remove this 'ack once we have a better way to stop this thing from\n"
3325 " float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3326 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3327 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3328 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3329 " ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3330 " color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord).rgb) * ReflectColor.rgb, ReflectColor.a);\n"
3333 " gl_FragColor = float4(color);\n"
3335 "#endif // FRAGMENT_SHADER\n"
3337 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3338 "#endif // !MODE_DEFERREDGEOMETRY\n"
3339 "#endif // !MODE_WATER\n"
3340 "#endif // !MODE_REFRACTION\n"
3341 "#endif // !MODE_BLOOMBLUR\n"
3342 "#endif // !MODE_GENERIC\n"
3343 "#endif // !MODE_POSTPROCESS\n"
3344 "#endif // !MODE_SHOWDEPTH\n"
3345 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3348 char *glslshaderstring = NULL;
3349 char *hlslshaderstring = NULL;
3351 //=======================================================================================================================================================
3353 typedef struct shaderpermutationinfo_s
3355 const char *pretext;
3358 shaderpermutationinfo_t;
3360 typedef struct shadermodeinfo_s
3362 const char *vertexfilename;
3363 const char *geometryfilename;
3364 const char *fragmentfilename;
3365 const char *pretext;
3370 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3371 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3373 {"#define USEDIFFUSE\n", " diffuse"},
3374 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3375 {"#define USEVIEWTINT\n", " viewtint"},
3376 {"#define USECOLORMAPPING\n", " colormapping"},
3377 {"#define USESATURATION\n", " saturation"},
3378 {"#define USEFOGINSIDE\n", " foginside"},
3379 {"#define USEFOGOUTSIDE\n", " fogoutside"},
3380 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
3381 {"#define USEGAMMARAMPS\n", " gammaramps"},
3382 {"#define USECUBEFILTER\n", " cubefilter"},
3383 {"#define USEGLOW\n", " glow"},
3384 {"#define USEBLOOM\n", " bloom"},
3385 {"#define USESPECULAR\n", " specular"},
3386 {"#define USEPOSTPROCESSING\n", " postprocessing"},
3387 {"#define USEREFLECTION\n", " reflection"},
3388 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3389 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3390 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3391 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3392 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3393 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3394 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3395 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
3396 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3397 {"#define USEALPHAKILL\n", " alphakill"},
3398 {"#define USEREFLECTCUBE\n", " reflectcube"},
3399 {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
3400 {"#define USEBOUNCEGRID\n", " bouncegrid"},
3403 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3404 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3406 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3407 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3408 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3409 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3410 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3411 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3412 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
3413 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3414 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3415 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3416 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3417 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3418 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3419 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3420 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3421 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3424 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
3426 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
3427 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3428 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3429 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3430 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3431 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3432 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
3433 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3434 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3435 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3436 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3437 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
3438 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
3439 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3440 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3441 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3444 struct r_glsl_permutation_s;
3445 typedef struct r_glsl_permutation_s
3447 /// hash lookup data
3448 struct r_glsl_permutation_s *hashnext;
3450 unsigned int permutation;
3452 /// indicates if we have tried compiling this permutation already
3454 /// 0 if compilation failed
3456 // texture units assigned to each detected uniform
3457 int tex_Texture_First;
3458 int tex_Texture_Second;
3459 int tex_Texture_GammaRamps;
3460 int tex_Texture_Normal;
3461 int tex_Texture_Color;
3462 int tex_Texture_Gloss;
3463 int tex_Texture_Glow;
3464 int tex_Texture_SecondaryNormal;
3465 int tex_Texture_SecondaryColor;
3466 int tex_Texture_SecondaryGloss;
3467 int tex_Texture_SecondaryGlow;
3468 int tex_Texture_Pants;
3469 int tex_Texture_Shirt;
3470 int tex_Texture_FogHeightTexture;
3471 int tex_Texture_FogMask;
3472 int tex_Texture_Lightmap;
3473 int tex_Texture_Deluxemap;
3474 int tex_Texture_Attenuation;
3475 int tex_Texture_Cube;
3476 int tex_Texture_Refraction;
3477 int tex_Texture_Reflection;
3478 int tex_Texture_ShadowMap2D;
3479 int tex_Texture_CubeProjection;
3480 int tex_Texture_ScreenDepth;
3481 int tex_Texture_ScreenNormalMap;
3482 int tex_Texture_ScreenDiffuse;
3483 int tex_Texture_ScreenSpecular;
3484 int tex_Texture_ReflectMask;
3485 int tex_Texture_ReflectCube;
3486 int tex_Texture_BounceGrid;
3487 /// locations of detected uniforms in program object, or -1 if not found
3488 int loc_Texture_First;
3489 int loc_Texture_Second;
3490 int loc_Texture_GammaRamps;
3491 int loc_Texture_Normal;
3492 int loc_Texture_Color;
3493 int loc_Texture_Gloss;
3494 int loc_Texture_Glow;
3495 int loc_Texture_SecondaryNormal;
3496 int loc_Texture_SecondaryColor;
3497 int loc_Texture_SecondaryGloss;
3498 int loc_Texture_SecondaryGlow;
3499 int loc_Texture_Pants;
3500 int loc_Texture_Shirt;
3501 int loc_Texture_FogHeightTexture;
3502 int loc_Texture_FogMask;
3503 int loc_Texture_Lightmap;
3504 int loc_Texture_Deluxemap;
3505 int loc_Texture_Attenuation;
3506 int loc_Texture_Cube;
3507 int loc_Texture_Refraction;
3508 int loc_Texture_Reflection;
3509 int loc_Texture_ShadowMap2D;
3510 int loc_Texture_CubeProjection;
3511 int loc_Texture_ScreenDepth;
3512 int loc_Texture_ScreenNormalMap;
3513 int loc_Texture_ScreenDiffuse;
3514 int loc_Texture_ScreenSpecular;
3515 int loc_Texture_ReflectMask;
3516 int loc_Texture_ReflectCube;
3517 int loc_Texture_BounceGrid;
3519 int loc_BloomBlur_Parameters;
3521 int loc_Color_Ambient;
3522 int loc_Color_Diffuse;
3523 int loc_Color_Specular;
3525 int loc_Color_Pants;
3526 int loc_Color_Shirt;
3527 int loc_DeferredColor_Ambient;
3528 int loc_DeferredColor_Diffuse;
3529 int loc_DeferredColor_Specular;
3530 int loc_DeferredMod_Diffuse;
3531 int loc_DeferredMod_Specular;
3532 int loc_DistortScaleRefractReflect;
3533 int loc_EyePosition;
3535 int loc_FogHeightFade;
3537 int loc_FogPlaneViewDist;
3538 int loc_FogRangeRecip;
3541 int loc_LightPosition;
3542 int loc_OffsetMapping_Scale;
3544 int loc_ReflectColor;
3545 int loc_ReflectFactor;
3546 int loc_ReflectOffset;
3547 int loc_RefractColor;
3549 int loc_ScreenCenterRefractReflect;
3550 int loc_ScreenScaleRefractReflect;
3551 int loc_ScreenToDepth;
3552 int loc_ShadowMap_Parameters;
3553 int loc_ShadowMap_TextureScale;
3554 int loc_SpecularPower;
3559 int loc_ViewTintColor;
3560 int loc_ViewToLight;
3561 int loc_ModelToLight;
3563 int loc_BackgroundTexMatrix;
3564 int loc_ModelViewProjectionMatrix;
3565 int loc_ModelViewMatrix;
3566 int loc_PixelToScreenTexCoord;
3567 int loc_ModelToReflectCube;
3568 int loc_ShadowMapMatrix;
3569 int loc_BloomColorSubtract;
3570 int loc_NormalmapScrollBlend;
3571 int loc_BounceGridMatrix;
3572 int loc_BounceGridIntensity;
3574 r_glsl_permutation_t;
3576 #define SHADERPERMUTATION_HASHSIZE 256
3579 // non-degradable "lightweight" shader parameters to keep the permutations simpler
3580 // these can NOT degrade! only use for simple stuff
3583 SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
3584 SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3585 SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
3586 SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
3587 SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
3588 SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5 ///< postprocess uservec4 is enabled
3590 #define SHADERSTATICPARMS_COUNT 6
3592 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
3593 static int shaderstaticparms_count = 0;
3595 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
3596 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
3597 qboolean R_CompileShader_CheckStaticParms(void)
3599 static int r_compileshader_staticparms_save[1];
3600 memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
3601 memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
3604 if (r_glsl_saturation_redcompensate.integer)
3605 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
3606 if (r_shadow_glossexact.integer)
3607 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
3608 if (r_glsl_postprocess.integer)
3610 if (r_glsl_postprocess_uservec1_enable.integer)
3611 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
3612 if (r_glsl_postprocess_uservec2_enable.integer)
3613 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
3614 if (r_glsl_postprocess_uservec3_enable.integer)
3615 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
3616 if (r_glsl_postprocess_uservec4_enable.integer)
3617 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
3619 return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
3622 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
3623 if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
3624 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
3626 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
3627 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
3629 shaderstaticparms_count = 0;
3632 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
3633 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
3634 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
3635 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
3636 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
3637 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
3640 /// information about each possible shader permutation
3641 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3642 /// currently selected permutation
3643 r_glsl_permutation_t *r_glsl_permutation;
3644 /// storage for permutations linked in the hash table
3645 memexpandablearray_t r_glsl_permutationarray;
3647 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3649 //unsigned int hashdepth = 0;
3650 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3651 r_glsl_permutation_t *p;
3652 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3654 if (p->mode == mode && p->permutation == permutation)
3656 //if (hashdepth > 10)
3657 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3662 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3664 p->permutation = permutation;
3665 p->hashnext = r_glsl_permutationhash[mode][hashindex];
3666 r_glsl_permutationhash[mode][hashindex] = p;
3667 //if (hashdepth > 10)
3668 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3672 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3675 if (!filename || !filename[0])
3677 if (!strcmp(filename, "glsl/default.glsl"))
3679 if (!glslshaderstring)
3681 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3682 if (glslshaderstring)
3683 Con_DPrintf("Loading shaders from file %s...\n", filename);
3685 glslshaderstring = (char *)builtinshaderstring;
3687 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3688 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3689 return shaderstring;
3691 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3694 if (printfromdisknotice)
3695 Con_DPrintf("from disk %s... ", filename);
3696 return shaderstring;
3698 return shaderstring;
3701 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3705 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3706 char *vertexstring, *geometrystring, *fragmentstring;
3707 char permutationname[256];
3708 int vertstrings_count = 0;
3709 int geomstrings_count = 0;
3710 int fragstrings_count = 0;
3711 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3712 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3713 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3720 permutationname[0] = 0;
3721 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
3722 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3723 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3725 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3727 // the first pretext is which type of shader to compile as
3728 // (later these will all be bound together as a program object)
3729 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3730 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3731 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3733 // the second pretext is the mode (for example a light source)
3734 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3735 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3736 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3737 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3739 // now add all the permutation pretexts
3740 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3742 if (permutation & (1<<i))
3744 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3745 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3746 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3747 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3751 // keep line numbers correct
3752 vertstrings_list[vertstrings_count++] = "\n";
3753 geomstrings_list[geomstrings_count++] = "\n";
3754 fragstrings_list[fragstrings_count++] = "\n";
3759 R_CompileShader_AddStaticParms(mode, permutation);
3760 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3761 vertstrings_count += shaderstaticparms_count;
3762 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3763 geomstrings_count += shaderstaticparms_count;
3764 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3765 fragstrings_count += shaderstaticparms_count;
3767 // now append the shader text itself
3768 vertstrings_list[vertstrings_count++] = vertexstring;
3769 geomstrings_list[geomstrings_count++] = geometrystring;
3770 fragstrings_list[fragstrings_count++] = fragmentstring;
3772 // if any sources were NULL, clear the respective list
3774 vertstrings_count = 0;
3775 if (!geometrystring)
3776 geomstrings_count = 0;
3777 if (!fragmentstring)
3778 fragstrings_count = 0;
3780 // compile the shader program
3781 if (vertstrings_count + geomstrings_count + fragstrings_count)
3782 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3786 qglUseProgram(p->program);CHECKGLERROR
3787 // look up all the uniform variable names we care about, so we don't
3788 // have to look them up every time we set them
3790 p->loc_Texture_First = qglGetUniformLocation(p->program, "Texture_First");
3791 p->loc_Texture_Second = qglGetUniformLocation(p->program, "Texture_Second");
3792 p->loc_Texture_GammaRamps = qglGetUniformLocation(p->program, "Texture_GammaRamps");
3793 p->loc_Texture_Normal = qglGetUniformLocation(p->program, "Texture_Normal");
3794 p->loc_Texture_Color = qglGetUniformLocation(p->program, "Texture_Color");
3795 p->loc_Texture_Gloss = qglGetUniformLocation(p->program, "Texture_Gloss");
3796 p->loc_Texture_Glow = qglGetUniformLocation(p->program, "Texture_Glow");
3797 p->loc_Texture_SecondaryNormal = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
3798 p->loc_Texture_SecondaryColor = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
3799 p->loc_Texture_SecondaryGloss = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
3800 p->loc_Texture_SecondaryGlow = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
3801 p->loc_Texture_Pants = qglGetUniformLocation(p->program, "Texture_Pants");
3802 p->loc_Texture_Shirt = qglGetUniformLocation(p->program, "Texture_Shirt");
3803 p->loc_Texture_FogHeightTexture = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
3804 p->loc_Texture_FogMask = qglGetUniformLocation(p->program, "Texture_FogMask");
3805 p->loc_Texture_Lightmap = qglGetUniformLocation(p->program, "Texture_Lightmap");
3806 p->loc_Texture_Deluxemap = qglGetUniformLocation(p->program, "Texture_Deluxemap");
3807 p->loc_Texture_Attenuation = qglGetUniformLocation(p->program, "Texture_Attenuation");
3808 p->loc_Texture_Cube = qglGetUniformLocation(p->program, "Texture_Cube");
3809 p->loc_Texture_Refraction = qglGetUniformLocation(p->program, "Texture_Refraction");
3810 p->loc_Texture_Reflection = qglGetUniformLocation(p->program, "Texture_Reflection");
3811 p->loc_Texture_ShadowMap2D = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
3812 p->loc_Texture_CubeProjection = qglGetUniformLocation(p->program, "Texture_CubeProjection");
3813 p->loc_Texture_ScreenDepth = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
3814 p->loc_Texture_ScreenNormalMap = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
3815 p->loc_Texture_ScreenDiffuse = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
3816 p->loc_Texture_ScreenSpecular = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
3817 p->loc_Texture_ReflectMask = qglGetUniformLocation(p->program, "Texture_ReflectMask");
3818 p->loc_Texture_ReflectCube = qglGetUniformLocation(p->program, "Texture_ReflectCube");
3819 p->loc_Texture_BounceGrid = qglGetUniformLocation(p->program, "Texture_BounceGrid");
3820 p->loc_Alpha = qglGetUniformLocation(p->program, "Alpha");
3821 p->loc_BloomBlur_Parameters = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
3822 p->loc_ClientTime = qglGetUniformLocation(p->program, "ClientTime");
3823 p->loc_Color_Ambient = qglGetUniformLocation(p->program, "Color_Ambient");
3824 p->loc_Color_Diffuse = qglGetUniformLocation(p->program, "Color_Diffuse");
3825 p->loc_Color_Specular = qglGetUniformLocation(p->program, "Color_Specular");
3826 p->loc_Color_Glow = qglGetUniformLocation(p->program, "Color_Glow");
3827 p->loc_Color_Pants = qglGetUniformLocation(p->program, "Color_Pants");
3828 p->loc_Color_Shirt = qglGetUniformLocation(p->program, "Color_Shirt");
3829 p->loc_DeferredColor_Ambient = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
3830 p->loc_DeferredColor_Diffuse = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
3831 p->loc_DeferredColor_Specular = qglGetUniformLocation(p->program, "DeferredColor_Specular");
3832 p->loc_DeferredMod_Diffuse = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
3833 p->loc_DeferredMod_Specular = qglGetUniformLocation(p->program, "DeferredMod_Specular");
3834 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
3835 p->loc_EyePosition = qglGetUniformLocation(p->program, "EyePosition");
3836 p->loc_FogColor = qglGetUniformLocation(p->program, "FogColor");
3837 p->loc_FogHeightFade = qglGetUniformLocation(p->program, "FogHeightFade");
3838 p->loc_FogPlane = qglGetUniformLocation(p->program, "FogPlane");
3839 p->loc_FogPlaneViewDist = qglGetUniformLocation(p->program, "FogPlaneViewDist");
3840 p->loc_FogRangeRecip = qglGetUniformLocation(p->program, "FogRangeRecip");
3841 p->loc_LightColor = qglGetUniformLocation(p->program, "LightColor");
3842 p->loc_LightDir = qglGetUniformLocation(p->program, "LightDir");
3843 p->loc_LightPosition = qglGetUniformLocation(p->program, "LightPosition");
3844 p->loc_OffsetMapping_Scale = qglGetUniformLocation(p->program, "OffsetMapping_Scale");
3845 p->loc_PixelSize = qglGetUniformLocation(p->program, "PixelSize");
3846 p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor");
3847 p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor");
3848 p->loc_ReflectOffset = qglGetUniformLocation(p->program, "ReflectOffset");
3849 p->loc_RefractColor = qglGetUniformLocation(p->program, "RefractColor");
3850 p->loc_Saturation = qglGetUniformLocation(p->program, "Saturation");
3851 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
3852 p->loc_ScreenScaleRefractReflect = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
3853 p->loc_ScreenToDepth = qglGetUniformLocation(p->program, "ScreenToDepth");
3854 p->loc_ShadowMap_Parameters = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
3855 p->loc_ShadowMap_TextureScale = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
3856 p->loc_SpecularPower = qglGetUniformLocation(p->program, "SpecularPower");
3857 p->loc_UserVec1 = qglGetUniformLocation(p->program, "UserVec1");
3858 p->loc_UserVec2 = qglGetUniformLocation(p->program, "UserVec2");
3859 p->loc_UserVec3 = qglGetUniformLocation(p->program, "UserVec3");
3860 p->loc_UserVec4 = qglGetUniformLocation(p->program, "UserVec4");
3861 p->loc_ViewTintColor = qglGetUniformLocation(p->program, "ViewTintColor");
3862 p->loc_ViewToLight = qglGetUniformLocation(p->program, "ViewToLight");
3863 p->loc_ModelToLight = qglGetUniformLocation(p->program, "ModelToLight");
3864 p->loc_TexMatrix = qglGetUniformLocation(p->program, "TexMatrix");
3865 p->loc_BackgroundTexMatrix = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
3866 p->loc_ModelViewMatrix = qglGetUniformLocation(p->program, "ModelViewMatrix");
3867 p->loc_ModelViewProjectionMatrix = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
3868 p->loc_PixelToScreenTexCoord = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
3869 p->loc_ModelToReflectCube = qglGetUniformLocation(p->program, "ModelToReflectCube");
3870 p->loc_ShadowMapMatrix = qglGetUniformLocation(p->program, "ShadowMapMatrix");
3871 p->loc_BloomColorSubtract = qglGetUniformLocation(p->program, "BloomColorSubtract");
3872 p->loc_NormalmapScrollBlend = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
3873 p->loc_BounceGridMatrix = qglGetUniformLocation(p->program, "BounceGridMatrix");
3874 p->loc_BounceGridIntensity = qglGetUniformLocation(p->program, "BounceGridIntensity");
3875 // initialize the samplers to refer to the texture units we use
3876 p->tex_Texture_First = -1;
3877 p->tex_Texture_Second = -1;
3878 p->tex_Texture_GammaRamps = -1;
3879 p->tex_Texture_Normal = -1;
3880 p->tex_Texture_Color = -1;
3881 p->tex_Texture_Gloss = -1;
3882 p->tex_Texture_Glow = -1;
3883 p->tex_Texture_SecondaryNormal = -1;
3884 p->tex_Texture_SecondaryColor = -1;
3885 p->tex_Texture_SecondaryGloss = -1;
3886 p->tex_Texture_SecondaryGlow = -1;
3887 p->tex_Texture_Pants = -1;
3888 p->tex_Texture_Shirt = -1;
3889 p->tex_Texture_FogHeightTexture = -1;
3890 p->tex_Texture_FogMask = -1;
3891 p->tex_Texture_Lightmap = -1;
3892 p->tex_Texture_Deluxemap = -1;
3893 p->tex_Texture_Attenuation = -1;
3894 p->tex_Texture_Cube = -1;
3895 p->tex_Texture_Refraction = -1;
3896 p->tex_Texture_Reflection = -1;
3897 p->tex_Texture_ShadowMap2D = -1;
3898 p->tex_Texture_CubeProjection = -1;
3899 p->tex_Texture_ScreenDepth = -1;
3900 p->tex_Texture_ScreenNormalMap = -1;
3901 p->tex_Texture_ScreenDiffuse = -1;
3902 p->tex_Texture_ScreenSpecular = -1;
3903 p->tex_Texture_ReflectMask = -1;
3904 p->tex_Texture_ReflectCube = -1;
3905 p->tex_Texture_BounceGrid = -1;
3907 if (p->loc_Texture_First >= 0) {p->tex_Texture_First = sampler;qglUniform1i(p->loc_Texture_First , sampler);sampler++;}
3908 if (p->loc_Texture_Second >= 0) {p->tex_Texture_Second = sampler;qglUniform1i(p->loc_Texture_Second , sampler);sampler++;}
3909 if (p->loc_Texture_GammaRamps >= 0) {p->tex_Texture_GammaRamps = sampler;qglUniform1i(p->loc_Texture_GammaRamps , sampler);sampler++;}
3910 if (p->loc_Texture_Normal >= 0) {p->tex_Texture_Normal = sampler;qglUniform1i(p->loc_Texture_Normal , sampler);sampler++;}
3911 if (p->loc_Texture_Color >= 0) {p->tex_Texture_Color = sampler;qglUniform1i(p->loc_Texture_Color , sampler);sampler++;}
3912 if (p->loc_Texture_Gloss >= 0) {p->tex_Texture_Gloss = sampler;qglUniform1i(p->loc_Texture_Gloss , sampler);sampler++;}
3913 if (p->loc_Texture_Glow >= 0) {p->tex_Texture_Glow = sampler;qglUniform1i(p->loc_Texture_Glow , sampler);sampler++;}
3914 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
3915 if (p->loc_Texture_SecondaryColor >= 0) {p->tex_Texture_SecondaryColor = sampler;qglUniform1i(p->loc_Texture_SecondaryColor , sampler);sampler++;}
3916 if (p->loc_Texture_SecondaryGloss >= 0) {p->tex_Texture_SecondaryGloss = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss , sampler);sampler++;}
3917 if (p->loc_Texture_SecondaryGlow >= 0) {p->tex_Texture_SecondaryGlow = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow , sampler);sampler++;}
3918 if (p->loc_Texture_Pants >= 0) {p->tex_Texture_Pants = sampler;qglUniform1i(p->loc_Texture_Pants , sampler);sampler++;}
3919 if (p->loc_Texture_Shirt >= 0) {p->tex_Texture_Shirt = sampler;qglUniform1i(p->loc_Texture_Shirt , sampler);sampler++;}
3920 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
3921 if (p->loc_Texture_FogMask >= 0) {p->tex_Texture_FogMask = sampler;qglUniform1i(p->loc_Texture_FogMask , sampler);sampler++;}
3922 if (p->loc_Texture_Lightmap >= 0) {p->tex_Texture_Lightmap = sampler;qglUniform1i(p->loc_Texture_Lightmap , sampler);sampler++;}
3923 if (p->loc_Texture_Deluxemap >= 0) {p->tex_Texture_Deluxemap = sampler;qglUniform1i(p->loc_Texture_Deluxemap , sampler);sampler++;}
3924 if (p->loc_Texture_Attenuation >= 0) {p->tex_Texture_Attenuation = sampler;qglUniform1i(p->loc_Texture_Attenuation , sampler);sampler++;}
3925 if (p->loc_Texture_Cube >= 0) {p->tex_Texture_Cube = sampler;qglUniform1i(p->loc_Texture_Cube , sampler);sampler++;}
3926 if (p->loc_Texture_Refraction >= 0) {p->tex_Texture_Refraction = sampler;qglUniform1i(p->loc_Texture_Refraction , sampler);sampler++;}
3927 if (p->loc_Texture_Reflection >= 0) {p->tex_Texture_Reflection = sampler;qglUniform1i(p->loc_Texture_Reflection , sampler);sampler++;}
3928 if (p->loc_Texture_ShadowMap2D >= 0) {p->tex_Texture_ShadowMap2D = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D , sampler);sampler++;}
3929 if (p->loc_Texture_CubeProjection >= 0) {p->tex_Texture_CubeProjection = sampler;qglUniform1i(p->loc_Texture_CubeProjection , sampler);sampler++;}
3930 if (p->loc_Texture_ScreenDepth >= 0) {p->tex_Texture_ScreenDepth = sampler;qglUniform1i(p->loc_Texture_ScreenDepth , sampler);sampler++;}
3931 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
3932 if (p->loc_Texture_ScreenDiffuse >= 0) {p->tex_Texture_ScreenDiffuse = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse , sampler);sampler++;}
3933 if (p->loc_Texture_ScreenSpecular >= 0) {p->tex_Texture_ScreenSpecular = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular , sampler);sampler++;}
3934 if (p->loc_Texture_ReflectMask >= 0) {p->tex_Texture_ReflectMask = sampler;qglUniform1i(p->loc_Texture_ReflectMask , sampler);sampler++;}
3935 if (p->loc_Texture_ReflectCube >= 0) {p->tex_Texture_ReflectCube = sampler;qglUniform1i(p->loc_Texture_ReflectCube , sampler);sampler++;}
3936 if (p->loc_Texture_BounceGrid >= 0) {p->tex_Texture_BounceGrid = sampler;qglUniform1i(p->loc_Texture_BounceGrid , sampler);sampler++;}
3938 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
3941 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
3945 Mem_Free(vertexstring);
3947 Mem_Free(geometrystring);
3949 Mem_Free(fragmentstring);
3952 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3954 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3955 if (r_glsl_permutation != perm)
3957 r_glsl_permutation = perm;
3958 if (!r_glsl_permutation->program)
3960 if (!r_glsl_permutation->compiled)
3961 R_GLSL_CompilePermutation(perm, mode, permutation);
3962 if (!r_glsl_permutation->program)
3964 // remove features until we find a valid permutation
3966 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3968 // reduce i more quickly whenever it would not remove any bits
3969 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3970 if (!(permutation & j))
3973 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3974 if (!r_glsl_permutation->compiled)
3975 R_GLSL_CompilePermutation(perm, mode, permutation);
3976 if (r_glsl_permutation->program)
3979 if (i >= SHADERPERMUTATION_COUNT)
3981 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3982 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3983 qglUseProgram(0);CHECKGLERROR
3984 return; // no bit left to clear, entire mode is broken
3989 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
3991 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3992 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3993 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
4000 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
4001 extern D3DCAPS9 vid_d3d9caps;
4004 struct r_hlsl_permutation_s;
4005 typedef struct r_hlsl_permutation_s
4007 /// hash lookup data
4008 struct r_hlsl_permutation_s *hashnext;
4010 unsigned int permutation;
4012 /// indicates if we have tried compiling this permutation already
4014 /// NULL if compilation failed
4015 IDirect3DVertexShader9 *vertexshader;
4016 IDirect3DPixelShader9 *pixelshader;
4018 r_hlsl_permutation_t;
4020 typedef enum D3DVSREGISTER_e
4022 D3DVSREGISTER_TexMatrix = 0, // float4x4
4023 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
4024 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
4025 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
4026 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
4027 D3DVSREGISTER_ModelToLight = 20, // float4x4
4028 D3DVSREGISTER_EyePosition = 24,
4029 D3DVSREGISTER_FogPlane = 25,
4030 D3DVSREGISTER_LightDir = 26,
4031 D3DVSREGISTER_LightPosition = 27,
4035 typedef enum D3DPSREGISTER_e
4037 D3DPSREGISTER_Alpha = 0,
4038 D3DPSREGISTER_BloomBlur_Parameters = 1,
4039 D3DPSREGISTER_ClientTime = 2,
4040 D3DPSREGISTER_Color_Ambient = 3,
4041 D3DPSREGISTER_Color_Diffuse = 4,
4042 D3DPSREGISTER_Color_Specular = 5,
4043 D3DPSREGISTER_Color_Glow = 6,
4044 D3DPSREGISTER_Color_Pants = 7,
4045 D3DPSREGISTER_Color_Shirt = 8,
4046 D3DPSREGISTER_DeferredColor_Ambient = 9,
4047 D3DPSREGISTER_DeferredColor_Diffuse = 10,
4048 D3DPSREGISTER_DeferredColor_Specular = 11,
4049 D3DPSREGISTER_DeferredMod_Diffuse = 12,
4050 D3DPSREGISTER_DeferredMod_Specular = 13,
4051 D3DPSREGISTER_DistortScaleRefractReflect = 14,
4052 D3DPSREGISTER_EyePosition = 15, // unused
4053 D3DPSREGISTER_FogColor = 16,
4054 D3DPSREGISTER_FogHeightFade = 17,
4055 D3DPSREGISTER_FogPlane = 18,
4056 D3DPSREGISTER_FogPlaneViewDist = 19,
4057 D3DPSREGISTER_FogRangeRecip = 20,
4058 D3DPSREGISTER_LightColor = 21,
4059 D3DPSREGISTER_LightDir = 22, // unused
4060 D3DPSREGISTER_LightPosition = 23,
4061 D3DPSREGISTER_OffsetMapping_Scale = 24,
4062 D3DPSREGISTER_PixelSize = 25,
4063 D3DPSREGISTER_ReflectColor = 26,
4064 D3DPSREGISTER_ReflectFactor = 27,
4065 D3DPSREGISTER_ReflectOffset = 28,
4066 D3DPSREGISTER_RefractColor = 29,
4067 D3DPSREGISTER_Saturation = 30,
4068 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
4069 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
4070 D3DPSREGISTER_ScreenToDepth = 33,
4071 D3DPSREGISTER_ShadowMap_Parameters = 34,
4072 D3DPSREGISTER_ShadowMap_TextureScale = 35,
4073 D3DPSREGISTER_SpecularPower = 36,
4074 D3DPSREGISTER_UserVec1 = 37,
4075 D3DPSREGISTER_UserVec2 = 38,
4076 D3DPSREGISTER_UserVec3 = 39,
4077 D3DPSREGISTER_UserVec4 = 40,
4078 D3DPSREGISTER_ViewTintColor = 41,
4079 D3DPSREGISTER_PixelToScreenTexCoord = 42,
4080 D3DPSREGISTER_BloomColorSubtract = 43,
4081 D3DPSREGISTER_ViewToLight = 44, // float4x4
4082 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
4083 D3DPSREGISTER_NormalmapScrollBlend = 52,
4088 /// information about each possible shader permutation
4089 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4090 /// currently selected permutation
4091 r_hlsl_permutation_t *r_hlsl_permutation;
4092 /// storage for permutations linked in the hash table
4093 memexpandablearray_t r_hlsl_permutationarray;
4095 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
4097 //unsigned int hashdepth = 0;
4098 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4099 r_hlsl_permutation_t *p;
4100 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
4102 if (p->mode == mode && p->permutation == permutation)
4104 //if (hashdepth > 10)
4105 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4110 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
4112 p->permutation = permutation;
4113 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
4114 r_hlsl_permutationhash[mode][hashindex] = p;
4115 //if (hashdepth > 10)
4116 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4120 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
4123 if (!filename || !filename[0])
4125 if (!strcmp(filename, "hlsl/default.hlsl"))
4127 if (!hlslshaderstring)
4129 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4130 if (hlslshaderstring)
4131 Con_DPrintf("Loading shaders from file %s...\n", filename);
4133 hlslshaderstring = (char *)builtinhlslshaderstring;
4135 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
4136 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
4137 return shaderstring;
4139 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4142 if (printfromdisknotice)
4143 Con_DPrintf("from disk %s... ", filename);
4144 return shaderstring;
4146 return shaderstring;
4150 //#include <d3dx9shader.h>
4151 //#include <d3dx9mesh.h>
4153 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4155 DWORD *vsbin = NULL;
4156 DWORD *psbin = NULL;
4157 fs_offset_t vsbinsize;
4158 fs_offset_t psbinsize;
4159 // IDirect3DVertexShader9 *vs = NULL;
4160 // IDirect3DPixelShader9 *ps = NULL;
4161 ID3DXBuffer *vslog = NULL;
4162 ID3DXBuffer *vsbuffer = NULL;
4163 ID3DXConstantTable *vsconstanttable = NULL;
4164 ID3DXBuffer *pslog = NULL;
4165 ID3DXBuffer *psbuffer = NULL;
4166 ID3DXConstantTable *psconstanttable = NULL;
4169 char temp[MAX_INPUTLINE];
4170 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
4171 qboolean debugshader = gl_paranoid.integer != 0;
4172 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4173 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4176 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
4177 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
4179 if ((!vsbin && vertstring) || (!psbin && fragstring))
4181 const char* dllnames_d3dx9 [] =
4205 dllhandle_t d3dx9_dll = NULL;
4206 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4207 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
4208 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4209 dllfunction_t d3dx9_dllfuncs[] =
4211 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
4212 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
4213 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
4216 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
4218 DWORD shaderflags = 0;
4220 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
4221 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4222 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4223 if (vertstring && vertstring[0])
4227 // vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
4228 // FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
4229 FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
4230 vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4233 vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4236 vsbinsize = vsbuffer->GetBufferSize();
4237 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
4238 memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
4239 vsbuffer->Release();
4243 strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
4244 Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
4248 if (fragstring && fragstring[0])
4252 // psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
4253 // FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
4254 FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
4255 psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4258 psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4261 psbinsize = psbuffer->GetBufferSize();
4262 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
4263 memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
4264 psbuffer->Release();
4268 strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
4269 Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
4273 Sys_UnloadLibrary(&d3dx9_dll);
4276 Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
4280 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
4281 if (FAILED(vsresult))
4282 Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
4283 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
4284 if (FAILED(psresult))
4285 Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
4287 // free the shader data
4288 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4289 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4292 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
4295 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
4296 int vertstring_length = 0;
4297 int geomstring_length = 0;
4298 int fragstring_length = 0;
4300 char *vertexstring, *geometrystring, *fragmentstring;
4301 char *vertstring, *geomstring, *fragstring;
4302 char permutationname[256];
4303 char cachename[256];
4304 int vertstrings_count = 0;
4305 int geomstrings_count = 0;
4306 int fragstrings_count = 0;
4307 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4308 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4309 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4314 p->vertexshader = NULL;
4315 p->pixelshader = NULL;
4317 permutationname[0] = 0;
4319 vertexstring = R_HLSL_GetText(modeinfo->vertexfilename, true);
4320 geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
4321 fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
4323 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4324 strlcat(cachename, "hlsl/", sizeof(cachename));
4326 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
4327 vertstrings_count = 0;
4328 geomstrings_count = 0;
4329 fragstrings_count = 0;
4330 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
4331 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
4332 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
4334 // the first pretext is which type of shader to compile as
4335 // (later these will all be bound together as a program object)
4336 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4337 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4338 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4340 // the second pretext is the mode (for example a light source)
4341 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4342 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4343 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4344 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4345 strlcat(cachename, modeinfo->name, sizeof(cachename));
4347 // now add all the permutation pretexts
4348 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4350 if (permutation & (1<<i))
4352 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4353 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4354 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4355 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4356 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4360 // keep line numbers correct
4361 vertstrings_list[vertstrings_count++] = "\n";
4362 geomstrings_list[geomstrings_count++] = "\n";
4363 fragstrings_list[fragstrings_count++] = "\n";
4368 R_CompileShader_AddStaticParms(mode, permutation);
4369 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4370 vertstrings_count += shaderstaticparms_count;
4371 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4372 geomstrings_count += shaderstaticparms_count;
4373 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4374 fragstrings_count += shaderstaticparms_count;
4376 // replace spaces in the cachename with _ characters
4377 for (i = 0;cachename[i];i++)
4378 if (cachename[i] == ' ')
4381 // now append the shader text itself
4382 vertstrings_list[vertstrings_count++] = vertexstring;
4383 geomstrings_list[geomstrings_count++] = geometrystring;
4384 fragstrings_list[fragstrings_count++] = fragmentstring;
4386 // if any sources were NULL, clear the respective list
4388 vertstrings_count = 0;
4389 if (!geometrystring)
4390 geomstrings_count = 0;
4391 if (!fragmentstring)
4392 fragstrings_count = 0;
4394 vertstring_length = 0;
4395 for (i = 0;i < vertstrings_count;i++)
4396 vertstring_length += strlen(vertstrings_list[i]);
4397 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
4398 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4399 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4401 geomstring_length = 0;
4402 for (i = 0;i < geomstrings_count;i++)
4403 geomstring_length += strlen(geomstrings_list[i]);
4404 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
4405 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4406 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4408 fragstring_length = 0;
4409 for (i = 0;i < fragstrings_count;i++)
4410 fragstring_length += strlen(fragstrings_list[i]);
4411 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
4412 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4413 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4415 // try to load the cached shader, or generate one
4416 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
4418 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
4419 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
4421 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
4425 Mem_Free(vertstring);
4427 Mem_Free(geomstring);
4429 Mem_Free(fragstring);
4431 Mem_Free(vertexstring);
4433 Mem_Free(geometrystring);
4435 Mem_Free(fragmentstring);
4438 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
4439 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
4440 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);}
4441 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);}
4442 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);}
4443 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);}
4445 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
4446 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
4447 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);}
4448 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);}
4449 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);}
4450 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);}
4452 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
4454 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
4455 if (r_hlsl_permutation != perm)
4457 r_hlsl_permutation = perm;
4458 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4460 if (!r_hlsl_permutation->compiled)
4461 R_HLSL_CompilePermutation(perm, mode, permutation);
4462 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4464 // remove features until we find a valid permutation
4466 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4468 // reduce i more quickly whenever it would not remove any bits
4469 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4470 if (!(permutation & j))
4473 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4474 if (!r_hlsl_permutation->compiled)
4475 R_HLSL_CompilePermutation(perm, mode, permutation);
4476 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
4479 if (i >= SHADERPERMUTATION_COUNT)
4481 //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4482 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4483 return; // no bit left to clear, entire mode is broken
4487 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
4488 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
4490 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
4491 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
4492 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
4496 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
4498 DPSOFTRAST_SetShader(mode, permutation);
4499 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
4500 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
4501 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
4504 void R_GLSL_Restart_f(void)
4506 unsigned int i, limit;
4507 if (glslshaderstring && glslshaderstring != builtinshaderstring)
4508 Mem_Free(glslshaderstring);
4509 glslshaderstring = NULL;
4510 if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
4511 Mem_Free(hlslshaderstring);
4512 hlslshaderstring = NULL;
4513 switch(vid.renderpath)
4515 case RENDERPATH_D3D9:
4518 r_hlsl_permutation_t *p;
4519 r_hlsl_permutation = NULL;
4520 limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
4521 for (i = 0;i < limit;i++)
4523 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
4525 if (p->vertexshader)
4526 IDirect3DVertexShader9_Release(p->vertexshader);
4528 IDirect3DPixelShader9_Release(p->pixelshader);
4529 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
4532 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4536 case RENDERPATH_D3D10:
4537 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4539 case RENDERPATH_D3D11:
4540 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4542 case RENDERPATH_GL20:
4543 case RENDERPATH_GLES2:
4545 r_glsl_permutation_t *p;
4546 r_glsl_permutation = NULL;
4547 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
4548 for (i = 0;i < limit;i++)
4550 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
4552 GL_Backend_FreeProgram(p->program);
4553 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
4556 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4559 case RENDERPATH_GL13:
4560 case RENDERPATH_GL11:
4562 case RENDERPATH_SOFT:
4567 void R_GLSL_DumpShader_f(void)
4572 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
4575 FS_Print(file, "/* The engine may define the following macros:\n");
4576 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4577 for (i = 0;i < SHADERMODE_COUNT;i++)
4578 FS_Print(file, glslshadermodeinfo[i].pretext);
4579 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4580 FS_Print(file, shaderpermutationinfo[i].pretext);
4581 FS_Print(file, "*/\n");
4582 FS_Print(file, builtinshaderstring);
4584 Con_Printf("glsl/default.glsl written\n");
4587 Con_Printf("failed to write to glsl/default.glsl\n");
4589 file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
4592 FS_Print(file, "/* The engine may define the following macros:\n");
4593 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4594 for (i = 0;i < SHADERMODE_COUNT;i++)
4595 FS_Print(file, hlslshadermodeinfo[i].pretext);
4596 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4597 FS_Print(file, shaderpermutationinfo[i].pretext);
4598 FS_Print(file, "*/\n");
4599 FS_Print(file, builtinhlslshaderstring);
4601 Con_Printf("hlsl/default.hlsl written\n");
4604 Con_Printf("failed to write to hlsl/default.hlsl\n");
4607 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
4610 texturemode = GL_MODULATE;
4611 switch (vid.renderpath)
4613 case RENDERPATH_D3D9:
4615 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))));
4616 R_Mesh_TexBind(GL20TU_FIRST , first );
4617 R_Mesh_TexBind(GL20TU_SECOND, second);
4620 case RENDERPATH_D3D10:
4621 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4623 case RENDERPATH_D3D11:
4624 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4626 case RENDERPATH_GL20:
4627 case RENDERPATH_GLES2:
4628 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))));
4629 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
4630 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
4632 case RENDERPATH_GL13:
4633 R_Mesh_TexBind(0, first );
4634 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
4635 R_Mesh_TexBind(1, second);
4637 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
4639 case RENDERPATH_GL11:
4640 R_Mesh_TexBind(0, first );
4642 case RENDERPATH_SOFT:
4643 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))));
4644 R_Mesh_TexBind(GL20TU_FIRST , first );
4645 R_Mesh_TexBind(GL20TU_SECOND, second);
4650 void R_SetupShader_DepthOrShadow(void)
4652 switch (vid.renderpath)
4654 case RENDERPATH_D3D9:
4656 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4659 case RENDERPATH_D3D10:
4660 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4662 case RENDERPATH_D3D11:
4663 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4665 case RENDERPATH_GL20:
4666 case RENDERPATH_GLES2:
4667 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4669 case RENDERPATH_GL13:
4670 R_Mesh_TexBind(0, 0);
4671 R_Mesh_TexBind(1, 0);
4673 case RENDERPATH_GL11:
4674 R_Mesh_TexBind(0, 0);
4676 case RENDERPATH_SOFT:
4677 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
4682 void R_SetupShader_ShowDepth(void)
4684 switch (vid.renderpath)
4686 case RENDERPATH_D3D9:
4688 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
4691 case RENDERPATH_D3D10:
4692 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4694 case RENDERPATH_D3D11:
4695 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4697 case RENDERPATH_GL20:
4698 case RENDERPATH_GLES2:
4699 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
4701 case RENDERPATH_GL13:
4703 case RENDERPATH_GL11:
4705 case RENDERPATH_SOFT:
4706 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
4711 extern qboolean r_shadow_usingdeferredprepass;
4712 extern cvar_t r_shadow_deferred_8bitrange;
4713 extern rtexture_t *r_shadow_attenuationgradienttexture;
4714 extern rtexture_t *r_shadow_attenuation2dtexture;
4715 extern rtexture_t *r_shadow_attenuation3dtexture;
4716 extern qboolean r_shadow_usingshadowmap2d;
4717 extern qboolean r_shadow_usingshadowmaportho;
4718 extern float r_shadow_shadowmap_texturescale[2];
4719 extern float r_shadow_shadowmap_parameters[4];
4720 extern qboolean r_shadow_shadowmapvsdct;
4721 extern qboolean r_shadow_shadowmapsampler;
4722 extern int r_shadow_shadowmappcf;
4723 extern rtexture_t *r_shadow_shadowmap2dtexture;
4724 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
4725 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
4726 extern matrix4x4_t r_shadow_shadowmapmatrix;
4727 extern int r_shadow_shadowmaplod; // changes for each light based on distance
4728 extern int r_shadow_prepass_width;
4729 extern int r_shadow_prepass_height;
4730 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
4731 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
4732 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
4733 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
4734 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
4735 static qboolean R_BlendFuncAllowsColormod(int src, int dst)
4737 // a blendfunc allows colormod if:
4738 // a) it can never keep the destination pixel invariant, or
4739 // b) it can keep the destination pixel invariant, and still can do so if colormodded
4740 // this is to prevent unintended side effects from colormod
4743 // IF there is a (s, sa) for which for all (d, da),
4744 // s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
4745 // THEN, for this (s, sa) and all (colormod, d, da):
4746 // s*colormod * src(s*colormod, d, sa, da) + d * dst(s*colormod, d, sa, da) == d
4747 // OBVIOUSLY, this means that
4748 // s*colormod * src(s*colormod, d, sa, da) = 0
4749 // dst(s*colormod, d, sa, da) = 1
4751 // note: not caring about GL_SRC_ALPHA_SATURATE and following here, these are unused in DP code
4753 // main condition to leave dst color invariant:
4754 // s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
4756 // s * 0 + d * dst(s, d, sa, da) == d
4757 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4758 // => colormod is a problem for GL_SRC_COLOR only
4760 // s + d * dst(s, d, sa, da) == d
4762 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4763 // => colormod is never problematic for these
4764 // src == GL_SRC_COLOR:
4765 // s*s + d * dst(s, d, sa, da) == d
4767 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4768 // => colormod is never problematic for these
4769 // src == GL_ONE_MINUS_SRC_COLOR:
4770 // s*(1-s) + d * dst(s, d, sa, da) == d
4771 // => s == 0 or s == 1
4772 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4773 // => colormod is a problem for GL_SRC_COLOR only
4774 // src == GL_DST_COLOR
4775 // s*d + d * dst(s, d, sa, da) == d
4777 // => dst == GL_ZERO/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4778 // => colormod is always a problem
4781 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4782 // => colormod is never problematic for these
4783 // => BUT, we do not know s! We must assume it is problematic
4784 // then... except in GL_ONE case, where we know all invariant
4786 // src == GL_ONE_MINUS_DST_COLOR
4787 // s*(1-d) + d * dst(s, d, sa, da) == d
4788 // => s == 0 (1-d is impossible to handle for our desired result)
4789 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4790 // => colormod is never problematic for these
4791 // src == GL_SRC_ALPHA
4792 // s*sa + d * dst(s, d, sa, da) == d
4793 // => s == 0, or sa == 0
4794 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4795 // => colormod breaks in the case GL_SRC_COLOR only
4796 // src == GL_ONE_MINUS_SRC_ALPHA
4797 // s*(1-sa) + d * dst(s, d, sa, da) == d
4798 // => s == 0, or sa == 1
4799 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4800 // => colormod breaks in the case GL_SRC_COLOR only
4801 // src == GL_DST_ALPHA
4802 // s*da + d * dst(s, d, sa, da) == d
4804 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4805 // => colormod is never problematic for these
4810 case GL_ONE_MINUS_SRC_COLOR:
4812 case GL_ONE_MINUS_SRC_ALPHA:
4813 if(dst == GL_SRC_COLOR)
4818 case GL_ONE_MINUS_DST_COLOR:
4820 case GL_ONE_MINUS_DST_ALPHA:
4830 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)
4832 // select a permutation of the lighting shader appropriate to this
4833 // combination of texture, entity, light source, and fogging, only use the
4834 // minimum features necessary to avoid wasting rendering time in the
4835 // fragment shader on features that are not being used
4836 unsigned int permutation = 0;
4837 unsigned int mode = 0;
4838 qboolean allow_colormod;
4839 static float dummy_colormod[3] = {1, 1, 1};
4840 float *colormod = rsurface.colormod;
4842 matrix4x4_t tempmatrix;
4843 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
4844 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4845 permutation |= SHADERPERMUTATION_ALPHAKILL;
4846 if (rsurfacepass == RSURFPASS_BACKGROUND)
4848 // distorted background
4849 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
4851 mode = SHADERMODE_WATER;
4852 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
4853 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND;
4854 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
4856 // this is the right thing to do for wateralpha
4857 GL_BlendFunc(GL_ONE, GL_ZERO);
4858 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
4862 // this is the right thing to do for entity alpha
4863 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4864 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4867 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
4869 mode = SHADERMODE_REFRACTION;
4870 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4871 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4875 mode = SHADERMODE_GENERIC;
4876 permutation |= SHADERPERMUTATION_DIFFUSE;
4877 GL_BlendFunc(GL_ONE, GL_ZERO);
4878 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
4881 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
4883 if (r_glsl_offsetmapping.integer)
4885 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4886 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4887 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4888 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4889 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4891 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4892 if (r_glsl_offsetmapping_reliefmapping.integer)
4893 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4896 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4897 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4898 // normalmap (deferred prepass), may use alpha test on diffuse
4899 mode = SHADERMODE_DEFERREDGEOMETRY;
4900 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4901 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4902 GL_BlendFunc(GL_ONE, GL_ZERO);
4903 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
4905 else if (rsurfacepass == RSURFPASS_RTLIGHT)
4907 if (r_glsl_offsetmapping.integer)
4909 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4910 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4911 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4912 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4913 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4915 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4916 if (r_glsl_offsetmapping_reliefmapping.integer)
4917 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4920 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4921 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4923 mode = SHADERMODE_LIGHTSOURCE;
4924 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4925 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4926 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
4927 permutation |= SHADERPERMUTATION_CUBEFILTER;
4928 if (diffusescale > 0)
4929 permutation |= SHADERPERMUTATION_DIFFUSE;
4930 if (specularscale > 0)
4931 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4932 if (r_refdef.fogenabled)
4933 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
4934 if (rsurface.texture->colormapping)
4935 permutation |= SHADERPERMUTATION_COLORMAPPING;
4936 if (r_shadow_usingshadowmap2d)
4938 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4939 if(r_shadow_shadowmapvsdct)
4940 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4942 if (r_shadow_shadowmapsampler)
4943 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4944 if (r_shadow_shadowmappcf > 1)
4945 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4946 else if (r_shadow_shadowmappcf)
4947 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4949 if (rsurface.texture->reflectmasktexture)
4950 permutation |= SHADERPERMUTATION_REFLECTCUBE;
4951 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4952 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE);
4954 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4956 if (r_glsl_offsetmapping.integer)
4958 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4959 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4960 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4961 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4962 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4964 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4965 if (r_glsl_offsetmapping_reliefmapping.integer)
4966 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4969 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4970 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4971 // unshaded geometry (fullbright or ambient model lighting)
4972 mode = SHADERMODE_FLATCOLOR;
4973 ambientscale = diffusescale = specularscale = 0;
4974 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4975 permutation |= SHADERPERMUTATION_GLOW;
4976 if (r_refdef.fogenabled)
4977 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
4978 if (rsurface.texture->colormapping)
4979 permutation |= SHADERPERMUTATION_COLORMAPPING;
4980 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4982 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4983 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4985 if (r_shadow_shadowmapsampler)
4986 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4987 if (r_shadow_shadowmappcf > 1)
4988 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4989 else if (r_shadow_shadowmappcf)
4990 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4992 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4993 permutation |= SHADERPERMUTATION_REFLECTION;
4994 if (rsurface.texture->reflectmasktexture)
4995 permutation |= SHADERPERMUTATION_REFLECTCUBE;
4996 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4997 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4999 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
5001 if (r_glsl_offsetmapping.integer)
5003 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5004 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5005 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5006 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5007 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5009 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5010 if (r_glsl_offsetmapping_reliefmapping.integer)
5011 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5014 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5015 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5016 // directional model lighting
5017 mode = SHADERMODE_LIGHTDIRECTION;
5018 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5019 permutation |= SHADERPERMUTATION_GLOW;
5020 permutation |= SHADERPERMUTATION_DIFFUSE;
5021 if (specularscale > 0)
5022 permutation |= SHADERPERMUTATION_SPECULAR;
5023 if (r_refdef.fogenabled)
5024 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5025 if (rsurface.texture->colormapping)
5026 permutation |= SHADERPERMUTATION_COLORMAPPING;
5027 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5029 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5030 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5032 if (r_shadow_shadowmapsampler)
5033 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5034 if (r_shadow_shadowmappcf > 1)
5035 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5036 else if (r_shadow_shadowmappcf)
5037 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5039 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5040 permutation |= SHADERPERMUTATION_REFLECTION;
5041 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5042 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5043 if (rsurface.texture->reflectmasktexture)
5044 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5045 if (r_shadow_bouncegridtexture)
5046 permutation |= SHADERPERMUTATION_BOUNCEGRID;
5047 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5048 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5050 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5052 if (r_glsl_offsetmapping.integer)
5054 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5055 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5056 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5057 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5058 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5060 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5061 if (r_glsl_offsetmapping_reliefmapping.integer)
5062 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5065 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5066 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5067 // ambient model lighting
5068 mode = SHADERMODE_LIGHTDIRECTION;
5069 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5070 permutation |= SHADERPERMUTATION_GLOW;
5071 if (r_refdef.fogenabled)
5072 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5073 if (rsurface.texture->colormapping)
5074 permutation |= SHADERPERMUTATION_COLORMAPPING;
5075 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5077 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5078 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5080 if (r_shadow_shadowmapsampler)
5081 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5082 if (r_shadow_shadowmappcf > 1)
5083 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5084 else if (r_shadow_shadowmappcf)
5085 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5087 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5088 permutation |= SHADERPERMUTATION_REFLECTION;
5089 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5090 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5091 if (rsurface.texture->reflectmasktexture)
5092 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5093 if (r_shadow_bouncegridtexture)
5094 permutation |= SHADERPERMUTATION_BOUNCEGRID;
5095 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5096 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5100 if (r_glsl_offsetmapping.integer)
5102 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5103 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5104 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5105 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5106 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5108 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5109 if (r_glsl_offsetmapping_reliefmapping.integer)
5110 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5113 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5114 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5116 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5117 permutation |= SHADERPERMUTATION_GLOW;
5118 if (r_refdef.fogenabled)
5119 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5120 if (rsurface.texture->colormapping)
5121 permutation |= SHADERPERMUTATION_COLORMAPPING;
5122 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5124 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5125 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5127 if (r_shadow_shadowmapsampler)
5128 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5129 if (r_shadow_shadowmappcf > 1)
5130 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5131 else if (r_shadow_shadowmappcf)
5132 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5134 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5135 permutation |= SHADERPERMUTATION_REFLECTION;
5136 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5137 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5138 if (rsurface.texture->reflectmasktexture)
5139 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5140 if (FAKELIGHT_ENABLED)
5142 // fake lightmapping (q1bsp, q3bsp, fullbright map)
5143 mode = SHADERMODE_FAKELIGHT;
5144 permutation |= SHADERPERMUTATION_DIFFUSE;
5145 if (specularscale > 0)
5146 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5148 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
5150 // deluxemapping (light direction texture)
5151 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
5152 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
5154 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5155 permutation |= SHADERPERMUTATION_DIFFUSE;
5156 if (specularscale > 0)
5157 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5159 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
5161 // fake deluxemapping (uniform light direction in tangentspace)
5162 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5163 permutation |= SHADERPERMUTATION_DIFFUSE;
5164 if (specularscale > 0)
5165 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5167 else if (rsurface.uselightmaptexture)
5169 // ordinary lightmapping (q1bsp, q3bsp)
5170 mode = SHADERMODE_LIGHTMAP;
5174 // ordinary vertex coloring (q3bsp)
5175 mode = SHADERMODE_VERTEXCOLOR;
5177 if (r_shadow_bouncegridtexture)
5178 permutation |= SHADERPERMUTATION_BOUNCEGRID;
5179 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5180 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5183 colormod = dummy_colormod;
5184 switch(vid.renderpath)
5186 case RENDERPATH_D3D9:
5188 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);
5189 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5190 R_SetupShader_SetPermutationHLSL(mode, permutation);
5191 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
5192 if (mode == SHADERMODE_LIGHTSOURCE)
5194 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
5195 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5199 if (mode == SHADERMODE_LIGHTDIRECTION)
5201 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5204 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
5205 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
5206 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
5207 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5208 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5210 if (mode == SHADERMODE_LIGHTSOURCE)
5212 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5213 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5214 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5215 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5216 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5218 // additive passes are only darkened by fog, not tinted
5219 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5220 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5224 if (mode == SHADERMODE_FLATCOLOR)
5226 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5228 else if (mode == SHADERMODE_LIGHTDIRECTION)
5230 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]);
5231 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5232 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);
5233 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);
5234 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5235 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
5236 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5240 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5241 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5242 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);
5243 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);
5244 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5246 // additive passes are only darkened by fog, not tinted
5247 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5248 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5250 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5251 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);
5252 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5253 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5254 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5255 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5256 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5257 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
5258 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5259 if (mode == SHADERMODE_WATER)
5260 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
5262 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5263 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5264 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5265 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));
5266 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5267 if (rsurface.texture->pantstexture)
5268 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5270 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
5271 if (rsurface.texture->shirttexture)
5272 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5274 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
5275 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5276 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
5277 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
5278 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
5279 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
5280 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5281 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5283 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
5284 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
5285 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
5286 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
5287 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
5288 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
5289 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
5290 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
5291 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
5292 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
5293 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
5294 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5295 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
5296 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
5297 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5298 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5299 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
5300 if (rsurfacepass == RSURFPASS_BACKGROUND)
5302 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5303 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5304 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5308 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5310 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
5311 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
5312 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
5313 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
5314 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5316 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
5317 if (rsurface.rtlight)
5319 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
5320 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
5325 case RENDERPATH_D3D10:
5326 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5328 case RENDERPATH_D3D11:
5329 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5331 case RENDERPATH_GL20:
5332 case RENDERPATH_GLES2:
5333 if (!vid.useinterleavedarrays)
5335 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);
5336 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5337 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5338 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5339 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5340 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5341 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5342 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5346 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);
5347 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5349 R_SetupShader_SetPermutationGLSL(mode, permutation);
5350 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
5351 if (mode == SHADERMODE_LIGHTSOURCE)
5353 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
5354 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5355 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5356 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5357 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5358 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);
5360 // additive passes are only darkened by fog, not tinted
5361 if (r_glsl_permutation->loc_FogColor >= 0)
5362 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5363 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5367 if (mode == SHADERMODE_FLATCOLOR)
5369 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5371 else if (mode == SHADERMODE_LIGHTDIRECTION)
5373 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]);
5374 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]);
5375 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);
5376 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);
5377 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);
5378 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]);
5379 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]);
5383 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]);
5384 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]);
5385 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);
5386 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);
5387 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);
5389 // additive passes are only darkened by fog, not tinted
5390 if (r_glsl_permutation->loc_FogColor >= 0)
5392 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5393 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5395 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5397 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);
5398 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]);
5399 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]);
5400 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]);
5401 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]);
5402 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5403 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
5404 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5405 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]);
5407 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
5408 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
5409 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
5410 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]);
5411 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]);
5413 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5414 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));
5415 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5416 if (r_glsl_permutation->loc_Color_Pants >= 0)
5418 if (rsurface.texture->pantstexture)
5419 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5421 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
5423 if (r_glsl_permutation->loc_Color_Shirt >= 0)
5425 if (rsurface.texture->shirttexture)
5426 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5428 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
5430 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]);
5431 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
5432 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
5433 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
5434 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5435 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]);
5436 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5437 if (r_glsl_permutation->loc_BounceGridMatrix >= 0) {Matrix4x4_Concat(&tempmatrix, &r_shadow_bouncegridmatrix, &rsurface.matrix);Matrix4x4_ToArrayFloatGL(&tempmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BounceGridMatrix, 1, false, m16f);}
5438 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity);
5440 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
5441 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
5442 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
5443 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
5444 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
5445 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
5446 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
5447 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
5448 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
5449 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
5450 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
5451 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
5452 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
5453 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
5454 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);
5455 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
5456 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
5457 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5458 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5459 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
5460 if (rsurfacepass == RSURFPASS_BACKGROUND)
5462 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);
5463 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);
5464 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);
5468 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);
5470 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
5471 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
5472 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
5473 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
5474 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5476 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture );
5477 if (rsurface.rtlight)
5479 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
5480 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
5483 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
5486 case RENDERPATH_GL13:
5487 case RENDERPATH_GL11:
5489 case RENDERPATH_SOFT:
5490 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);
5491 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
5492 R_SetupShader_SetPermutationSoft(mode, permutation);
5493 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
5494 if (mode == SHADERMODE_LIGHTSOURCE)
5496 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
5497 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5498 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5499 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5500 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5501 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5503 // additive passes are only darkened by fog, not tinted
5504 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
5505 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5509 if (mode == SHADERMODE_FLATCOLOR)
5511 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5513 else if (mode == SHADERMODE_LIGHTDIRECTION)
5515 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]);
5516 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5517 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);
5518 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);
5519 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5520 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]);
5521 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5525 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5526 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5527 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);
5528 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);
5529 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5531 // additive passes are only darkened by fog, not tinted
5532 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5533 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
5535 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5536 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);
5537 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5538 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5539 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]);
5540 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]);
5541 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5542 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
5543 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5544 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
5546 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
5547 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
5548 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
5549 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5550 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]);
5552 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5553 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));
5554 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5555 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
5557 if (rsurface.texture->pantstexture)
5558 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5560 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
5562 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
5564 if (rsurface.texture->shirttexture)
5565 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5567 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
5569 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5570 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
5571 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
5572 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
5573 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5574 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5575 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5577 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
5578 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
5579 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
5580 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
5581 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
5582 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
5583 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
5584 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
5585 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
5586 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
5587 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
5588 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5589 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
5590 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
5591 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5592 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5593 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
5594 if (rsurfacepass == RSURFPASS_BACKGROUND)
5596 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5597 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5598 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5602 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5604 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
5605 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
5606 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
5607 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
5608 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5610 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
5611 if (rsurface.rtlight)
5613 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
5614 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
5621 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
5623 // select a permutation of the lighting shader appropriate to this
5624 // combination of texture, entity, light source, and fogging, only use the
5625 // minimum features necessary to avoid wasting rendering time in the
5626 // fragment shader on features that are not being used
5627 unsigned int permutation = 0;
5628 unsigned int mode = 0;
5629 const float *lightcolorbase = rtlight->currentcolor;
5630 float ambientscale = rtlight->ambientscale;
5631 float diffusescale = rtlight->diffusescale;
5632 float specularscale = rtlight->specularscale;
5633 // this is the location of the light in view space
5634 vec3_t viewlightorigin;
5635 // this transforms from view space (camera) to light space (cubemap)
5636 matrix4x4_t viewtolight;
5637 matrix4x4_t lighttoview;
5638 float viewtolight16f[16];
5639 float range = 1.0f / r_shadow_deferred_8bitrange.value;
5641 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
5642 if (rtlight->currentcubemap != r_texture_whitecube)
5643 permutation |= SHADERPERMUTATION_CUBEFILTER;
5644 if (diffusescale > 0)
5645 permutation |= SHADERPERMUTATION_DIFFUSE;
5646 if (specularscale > 0)
5647 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5648 if (r_shadow_usingshadowmap2d)
5650 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5651 if (r_shadow_shadowmapvsdct)
5652 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5654 if (r_shadow_shadowmapsampler)
5655 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5656 if (r_shadow_shadowmappcf > 1)
5657 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5658 else if (r_shadow_shadowmappcf)
5659 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5661 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
5662 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
5663 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
5664 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
5665 switch(vid.renderpath)
5667 case RENDERPATH_D3D9:
5669 R_SetupShader_SetPermutationHLSL(mode, permutation);
5670 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
5671 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
5672 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
5673 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
5674 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
5675 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5676 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5677 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5678 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5679 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5681 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
5682 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthcolortexture );
5683 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
5684 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
5685 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dcolortexture );
5686 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
5689 case RENDERPATH_D3D10:
5690 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5692 case RENDERPATH_D3D11:
5693 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5695 case RENDERPATH_GL20:
5696 case RENDERPATH_GLES2:
5697 R_SetupShader_SetPermutationGLSL(mode, permutation);
5698 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
5699 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
5700 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);
5701 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);
5702 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);
5703 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]);
5704 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]);
5705 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));
5706 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]);
5707 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
5709 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
5710 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
5711 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
5712 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
5713 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );
5714 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
5716 case RENDERPATH_GL13:
5717 case RENDERPATH_GL11:
5719 case RENDERPATH_SOFT:
5720 R_SetupShader_SetPermutationGLSL(mode, permutation);
5721 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
5722 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
5723 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
5724 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
5725 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
5726 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5727 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]);
5728 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));
5729 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5730 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5732 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
5733 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
5734 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
5735 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
5736 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
5737 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
5742 #define SKINFRAME_HASH 1024
5746 int loadsequence; // incremented each level change
5747 memexpandablearray_t array;
5748 skinframe_t *hash[SKINFRAME_HASH];
5751 r_skinframe_t r_skinframe;
5753 void R_SkinFrame_PrepareForPurge(void)
5755 r_skinframe.loadsequence++;
5756 // wrap it without hitting zero
5757 if (r_skinframe.loadsequence >= 200)
5758 r_skinframe.loadsequence = 1;
5761 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
5765 // mark the skinframe as used for the purging code
5766 skinframe->loadsequence = r_skinframe.loadsequence;
5769 void R_SkinFrame_Purge(void)
5773 for (i = 0;i < SKINFRAME_HASH;i++)
5775 for (s = r_skinframe.hash[i];s;s = s->next)
5777 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
5779 if (s->merged == s->base)
5781 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
5782 R_PurgeTexture(s->stain );s->stain = NULL;
5783 R_PurgeTexture(s->merged);s->merged = NULL;
5784 R_PurgeTexture(s->base );s->base = NULL;
5785 R_PurgeTexture(s->pants );s->pants = NULL;
5786 R_PurgeTexture(s->shirt );s->shirt = NULL;
5787 R_PurgeTexture(s->nmap );s->nmap = NULL;
5788 R_PurgeTexture(s->gloss );s->gloss = NULL;
5789 R_PurgeTexture(s->glow );s->glow = NULL;
5790 R_PurgeTexture(s->fog );s->fog = NULL;
5791 R_PurgeTexture(s->reflect);s->reflect = NULL;
5792 s->loadsequence = 0;
5798 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
5800 char basename[MAX_QPATH];
5802 Image_StripImageExtension(name, basename, sizeof(basename));
5804 if( last == NULL ) {
5806 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5807 item = r_skinframe.hash[hashindex];
5812 // linearly search through the hash bucket
5813 for( ; item ; item = item->next ) {
5814 if( !strcmp( item->basename, basename ) ) {
5821 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
5825 char basename[MAX_QPATH];
5827 Image_StripImageExtension(name, basename, sizeof(basename));
5829 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5830 for (item = r_skinframe.hash[hashindex];item;item = item->next)
5831 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
5835 rtexture_t *dyntexture;
5836 // check whether its a dynamic texture
5837 dyntexture = CL_GetDynTexture( basename );
5838 if (!add && !dyntexture)
5840 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
5841 memset(item, 0, sizeof(*item));
5842 strlcpy(item->basename, basename, sizeof(item->basename));
5843 item->base = dyntexture; // either NULL or dyntexture handle
5844 item->textureflags = textureflags;
5845 item->comparewidth = comparewidth;
5846 item->compareheight = compareheight;
5847 item->comparecrc = comparecrc;
5848 item->next = r_skinframe.hash[hashindex];
5849 r_skinframe.hash[hashindex] = item;
5851 else if( item->base == NULL )
5853 rtexture_t *dyntexture;
5854 // check whether its a dynamic texture
5855 // 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]
5856 dyntexture = CL_GetDynTexture( basename );
5857 item->base = dyntexture; // either NULL or dyntexture handle
5860 R_SkinFrame_MarkUsed(item);
5864 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
5866 unsigned long long avgcolor[5], wsum; \
5874 for(pix = 0; pix < cnt; ++pix) \
5877 for(comp = 0; comp < 3; ++comp) \
5879 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
5882 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5884 for(comp = 0; comp < 3; ++comp) \
5885 avgcolor[comp] += getpixel * w; \
5888 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5889 avgcolor[4] += getpixel; \
5891 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
5893 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
5894 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
5895 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
5896 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
5899 extern cvar_t gl_picmip;
5900 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
5903 unsigned char *pixels;
5904 unsigned char *bumppixels;
5905 unsigned char *basepixels = NULL;
5906 int basepixels_width = 0;
5907 int basepixels_height = 0;
5908 skinframe_t *skinframe;
5909 rtexture_t *ddsbase = NULL;
5910 qboolean ddshasalpha = false;
5911 float ddsavgcolor[4];
5912 char basename[MAX_QPATH];
5913 int miplevel = R_PicmipForFlags(textureflags);
5914 int savemiplevel = miplevel;
5917 if (cls.state == ca_dedicated)
5920 // return an existing skinframe if already loaded
5921 // if loading of the first image fails, don't make a new skinframe as it
5922 // would cause all future lookups of this to be missing
5923 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5924 if (skinframe && skinframe->base)
5927 Image_StripImageExtension(name, basename, sizeof(basename));
5929 // check for DDS texture file first
5930 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
5932 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
5933 if (basepixels == NULL)
5937 // FIXME handle miplevel
5939 if (developer_loading.integer)
5940 Con_Printf("loading skin \"%s\"\n", name);
5942 // we've got some pixels to store, so really allocate this new texture now
5944 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
5945 skinframe->stain = NULL;
5946 skinframe->merged = NULL;
5947 skinframe->base = NULL;
5948 skinframe->pants = NULL;
5949 skinframe->shirt = NULL;
5950 skinframe->nmap = NULL;
5951 skinframe->gloss = NULL;
5952 skinframe->glow = NULL;
5953 skinframe->fog = NULL;
5954 skinframe->reflect = NULL;
5955 skinframe->hasalpha = false;
5959 skinframe->base = ddsbase;
5960 skinframe->hasalpha = ddshasalpha;
5961 VectorCopy(ddsavgcolor, skinframe->avgcolor);
5962 if (r_loadfog && skinframe->hasalpha)
5963 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
5964 //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]);
5968 basepixels_width = image_width;
5969 basepixels_height = image_height;
5970 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);
5971 if (textureflags & TEXF_ALPHA)
5973 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
5975 if (basepixels[j] < 255)
5977 skinframe->hasalpha = true;
5981 if (r_loadfog && skinframe->hasalpha)
5983 // has transparent pixels
5984 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5985 for (j = 0;j < image_width * image_height * 4;j += 4)
5990 pixels[j+3] = basepixels[j+3];
5992 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);
5996 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
5997 //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]);
5998 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
5999 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
6000 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
6001 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
6006 mymiplevel = savemiplevel;
6007 if (r_loadnormalmap)
6008 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);
6009 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6011 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6012 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6013 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6014 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6017 // _norm is the name used by tenebrae and has been adopted as standard
6018 if (r_loadnormalmap && skinframe->nmap == NULL)
6020 mymiplevel = savemiplevel;
6021 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6023 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);
6027 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6029 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6030 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
6031 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);
6033 Mem_Free(bumppixels);
6035 else if (r_shadow_bumpscale_basetexture.value > 0)
6037 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
6038 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
6039 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);
6042 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
6043 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
6046 // _luma is supported only for tenebrae compatibility
6047 // _glow is the preferred name
6048 mymiplevel = savemiplevel;
6049 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))))
6051 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);
6052 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
6053 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
6054 Mem_Free(pixels);pixels = NULL;
6057 mymiplevel = savemiplevel;
6058 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6060 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);
6061 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
6062 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
6067 mymiplevel = savemiplevel;
6068 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6070 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);
6071 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
6072 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
6077 mymiplevel = savemiplevel;
6078 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6080 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);
6081 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
6082 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
6087 mymiplevel = savemiplevel;
6088 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6090 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);
6091 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
6092 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
6098 Mem_Free(basepixels);
6103 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
6104 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
6107 unsigned char *temp1, *temp2;
6108 skinframe_t *skinframe;
6110 if (cls.state == ca_dedicated)
6113 // if already loaded just return it, otherwise make a new skinframe
6114 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
6115 if (skinframe && skinframe->base)
6118 skinframe->stain = NULL;
6119 skinframe->merged = NULL;
6120 skinframe->base = NULL;
6121 skinframe->pants = NULL;
6122 skinframe->shirt = NULL;
6123 skinframe->nmap = NULL;
6124 skinframe->gloss = NULL;
6125 skinframe->glow = NULL;
6126 skinframe->fog = NULL;
6127 skinframe->reflect = NULL;
6128 skinframe->hasalpha = false;
6130 // if no data was provided, then clearly the caller wanted to get a blank skinframe
6134 if (developer_loading.integer)
6135 Con_Printf("loading 32bit skin \"%s\"\n", name);
6137 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
6139 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6140 temp2 = temp1 + width * height * 4;
6141 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6142 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);
6145 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
6146 if (textureflags & TEXF_ALPHA)
6148 for (i = 3;i < width * height * 4;i += 4)
6150 if (skindata[i] < 255)
6152 skinframe->hasalpha = true;
6156 if (r_loadfog && skinframe->hasalpha)
6158 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
6159 memcpy(fogpixels, skindata, width * height * 4);
6160 for (i = 0;i < width * height * 4;i += 4)
6161 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
6162 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
6163 Mem_Free(fogpixels);
6167 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
6168 //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]);
6173 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
6177 skinframe_t *skinframe;
6179 if (cls.state == ca_dedicated)
6182 // if already loaded just return it, otherwise make a new skinframe
6183 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6184 if (skinframe && skinframe->base)
6187 skinframe->stain = NULL;
6188 skinframe->merged = NULL;
6189 skinframe->base = NULL;
6190 skinframe->pants = NULL;
6191 skinframe->shirt = NULL;
6192 skinframe->nmap = NULL;
6193 skinframe->gloss = NULL;
6194 skinframe->glow = NULL;
6195 skinframe->fog = NULL;
6196 skinframe->reflect = NULL;
6197 skinframe->hasalpha = false;
6199 // if no data was provided, then clearly the caller wanted to get a blank skinframe
6203 if (developer_loading.integer)
6204 Con_Printf("loading quake skin \"%s\"\n", name);
6206 // 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)
6207 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
6208 memcpy(skinframe->qpixels, skindata, width*height);
6209 skinframe->qwidth = width;
6210 skinframe->qheight = height;
6213 for (i = 0;i < width * height;i++)
6214 featuresmask |= palette_featureflags[skindata[i]];
6216 skinframe->hasalpha = false;
6217 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
6218 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
6219 skinframe->qgeneratemerged = true;
6220 skinframe->qgeneratebase = skinframe->qhascolormapping;
6221 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
6223 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
6224 //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]);
6229 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
6233 unsigned char *skindata;
6235 if (!skinframe->qpixels)
6238 if (!skinframe->qhascolormapping)
6239 colormapped = false;
6243 if (!skinframe->qgeneratebase)
6248 if (!skinframe->qgeneratemerged)
6252 width = skinframe->qwidth;
6253 height = skinframe->qheight;
6254 skindata = skinframe->qpixels;
6256 if (skinframe->qgeneratenmap)
6258 unsigned char *temp1, *temp2;
6259 skinframe->qgeneratenmap = false;
6260 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6261 temp2 = temp1 + width * height * 4;
6262 // use either a custom palette or the quake palette
6263 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
6264 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6265 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);
6269 if (skinframe->qgenerateglow)
6271 skinframe->qgenerateglow = false;
6272 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
6277 skinframe->qgeneratebase = false;
6278 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);
6279 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
6280 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
6284 skinframe->qgeneratemerged = false;
6285 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);
6288 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
6290 Mem_Free(skinframe->qpixels);
6291 skinframe->qpixels = NULL;
6295 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)
6298 skinframe_t *skinframe;
6300 if (cls.state == ca_dedicated)
6303 // if already loaded just return it, otherwise make a new skinframe
6304 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6305 if (skinframe && skinframe->base)
6308 skinframe->stain = NULL;
6309 skinframe->merged = NULL;
6310 skinframe->base = NULL;
6311 skinframe->pants = NULL;
6312 skinframe->shirt = NULL;
6313 skinframe->nmap = NULL;
6314 skinframe->gloss = NULL;
6315 skinframe->glow = NULL;
6316 skinframe->fog = NULL;
6317 skinframe->reflect = NULL;
6318 skinframe->hasalpha = false;
6320 // if no data was provided, then clearly the caller wanted to get a blank skinframe
6324 if (developer_loading.integer)
6325 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
6327 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
6328 if (textureflags & TEXF_ALPHA)
6330 for (i = 0;i < width * height;i++)
6332 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
6334 skinframe->hasalpha = true;
6338 if (r_loadfog && skinframe->hasalpha)
6339 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
6342 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
6343 //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]);
6348 skinframe_t *R_SkinFrame_LoadMissing(void)
6350 skinframe_t *skinframe;
6352 if (cls.state == ca_dedicated)
6355 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
6356 skinframe->stain = NULL;
6357 skinframe->merged = NULL;
6358 skinframe->base = NULL;
6359 skinframe->pants = NULL;
6360 skinframe->shirt = NULL;
6361 skinframe->nmap = NULL;
6362 skinframe->gloss = NULL;
6363 skinframe->glow = NULL;
6364 skinframe->fog = NULL;
6365 skinframe->reflect = NULL;
6366 skinframe->hasalpha = false;
6368 skinframe->avgcolor[0] = rand() / RAND_MAX;
6369 skinframe->avgcolor[1] = rand() / RAND_MAX;
6370 skinframe->avgcolor[2] = rand() / RAND_MAX;
6371 skinframe->avgcolor[3] = 1;
6376 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
6377 typedef struct suffixinfo_s
6380 qboolean flipx, flipy, flipdiagonal;
6383 static suffixinfo_t suffix[3][6] =
6386 {"px", false, false, false},
6387 {"nx", false, false, false},
6388 {"py", false, false, false},
6389 {"ny", false, false, false},
6390 {"pz", false, false, false},
6391 {"nz", false, false, false}
6394 {"posx", false, false, false},
6395 {"negx", false, false, false},
6396 {"posy", false, false, false},
6397 {"negy", false, false, false},
6398 {"posz", false, false, false},
6399 {"negz", false, false, false}
6402 {"rt", true, false, true},
6403 {"lf", false, true, true},
6404 {"ft", true, true, false},
6405 {"bk", false, false, false},
6406 {"up", true, false, true},
6407 {"dn", true, false, true}
6411 static int componentorder[4] = {0, 1, 2, 3};
6413 rtexture_t *R_LoadCubemap(const char *basename)
6415 int i, j, cubemapsize;
6416 unsigned char *cubemappixels, *image_buffer;
6417 rtexture_t *cubemaptexture;
6419 // must start 0 so the first loadimagepixels has no requested width/height
6421 cubemappixels = NULL;
6422 cubemaptexture = NULL;
6423 // keep trying different suffix groups (posx, px, rt) until one loads
6424 for (j = 0;j < 3 && !cubemappixels;j++)
6426 // load the 6 images in the suffix group
6427 for (i = 0;i < 6;i++)
6429 // generate an image name based on the base and and suffix
6430 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
6432 if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
6434 // an image loaded, make sure width and height are equal
6435 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
6437 // if this is the first image to load successfully, allocate the cubemap memory
6438 if (!cubemappixels && image_width >= 1)
6440 cubemapsize = image_width;
6441 // note this clears to black, so unavailable sides are black
6442 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
6444 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
6446 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);
6449 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
6451 Mem_Free(image_buffer);
6455 // if a cubemap loaded, upload it
6458 if (developer_loading.integer)
6459 Con_Printf("loading cubemap \"%s\"\n", basename);
6461 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6462 Mem_Free(cubemappixels);
6466 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
6467 if (developer_loading.integer)
6469 Con_Printf("(tried tried images ");
6470 for (j = 0;j < 3;j++)
6471 for (i = 0;i < 6;i++)
6472 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
6473 Con_Print(" and was unable to find any of them).\n");
6476 return cubemaptexture;
6479 rtexture_t *R_GetCubemap(const char *basename)
6482 for (i = 0;i < r_texture_numcubemaps;i++)
6483 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
6484 return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
6485 if (i >= MAX_CUBEMAPS)
6486 return r_texture_whitecube;
6487 r_texture_numcubemaps++;
6488 strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
6489 r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
6490 return r_texture_cubemaps[i].texture;
6493 void R_FreeCubemaps(void)
6496 for (i = 0;i < r_texture_numcubemaps;i++)
6498 if (developer_loading.integer)
6499 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
6500 if (r_texture_cubemaps[i].texture)
6501 R_FreeTexture(r_texture_cubemaps[i].texture);
6503 r_texture_numcubemaps = 0;
6506 void R_Main_FreeViewCache(void)
6508 if (r_refdef.viewcache.entityvisible)
6509 Mem_Free(r_refdef.viewcache.entityvisible);
6510 if (r_refdef.viewcache.world_pvsbits)
6511 Mem_Free(r_refdef.viewcache.world_pvsbits);
6512 if (r_refdef.viewcache.world_leafvisible)
6513 Mem_Free(r_refdef.viewcache.world_leafvisible);
6514 if (r_refdef.viewcache.world_surfacevisible)
6515 Mem_Free(r_refdef.viewcache.world_surfacevisible);
6516 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
6519 void R_Main_ResizeViewCache(void)
6521 int numentities = r_refdef.scene.numentities;
6522 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
6523 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
6524 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
6525 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
6526 if (r_refdef.viewcache.maxentities < numentities)
6528 r_refdef.viewcache.maxentities = numentities;
6529 if (r_refdef.viewcache.entityvisible)
6530 Mem_Free(r_refdef.viewcache.entityvisible);
6531 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
6533 if (r_refdef.viewcache.world_numclusters != numclusters)
6535 r_refdef.viewcache.world_numclusters = numclusters;
6536 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
6537 if (r_refdef.viewcache.world_pvsbits)
6538 Mem_Free(r_refdef.viewcache.world_pvsbits);
6539 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
6541 if (r_refdef.viewcache.world_numleafs != numleafs)
6543 r_refdef.viewcache.world_numleafs = numleafs;
6544 if (r_refdef.viewcache.world_leafvisible)
6545 Mem_Free(r_refdef.viewcache.world_leafvisible);
6546 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
6548 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
6550 r_refdef.viewcache.world_numsurfaces = numsurfaces;
6551 if (r_refdef.viewcache.world_surfacevisible)
6552 Mem_Free(r_refdef.viewcache.world_surfacevisible);
6553 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
6557 extern rtexture_t *loadingscreentexture;
6558 void gl_main_start(void)
6560 loadingscreentexture = NULL;
6561 r_texture_blanknormalmap = NULL;
6562 r_texture_white = NULL;
6563 r_texture_grey128 = NULL;
6564 r_texture_black = NULL;
6565 r_texture_whitecube = NULL;
6566 r_texture_normalizationcube = NULL;
6567 r_texture_fogattenuation = NULL;
6568 r_texture_fogheighttexture = NULL;
6569 r_texture_gammaramps = NULL;
6570 r_texture_numcubemaps = 0;
6572 r_loaddds = r_texture_dds_load.integer != 0;
6573 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
6575 switch(vid.renderpath)
6577 case RENDERPATH_GL20:
6578 case RENDERPATH_D3D9:
6579 case RENDERPATH_D3D10:
6580 case RENDERPATH_D3D11:
6581 case RENDERPATH_SOFT:
6582 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6583 Cvar_SetValueQuick(&gl_combine, 1);
6584 Cvar_SetValueQuick(&r_glsl, 1);
6585 r_loadnormalmap = true;
6589 case RENDERPATH_GL13:
6590 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6591 Cvar_SetValueQuick(&gl_combine, 1);
6592 Cvar_SetValueQuick(&r_glsl, 0);
6593 r_loadnormalmap = false;
6594 r_loadgloss = false;
6597 case RENDERPATH_GL11:
6598 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6599 Cvar_SetValueQuick(&gl_combine, 0);
6600 Cvar_SetValueQuick(&r_glsl, 0);
6601 r_loadnormalmap = false;
6602 r_loadgloss = false;
6605 case RENDERPATH_GLES2:
6606 Cvar_SetValueQuick(&r_textureunits, 1);
6607 Cvar_SetValueQuick(&gl_combine, 1);
6608 Cvar_SetValueQuick(&r_glsl, 1);
6609 r_loadnormalmap = true;
6610 r_loadgloss = false;
6616 R_FrameData_Reset();
6620 memset(r_queries, 0, sizeof(r_queries));
6622 r_qwskincache = NULL;
6623 r_qwskincache_size = 0;
6625 // set up r_skinframe loading system for textures
6626 memset(&r_skinframe, 0, sizeof(r_skinframe));
6627 r_skinframe.loadsequence = 1;
6628 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
6630 r_main_texturepool = R_AllocTexturePool();
6631 R_BuildBlankTextures();
6633 if (vid.support.arb_texture_cube_map)
6636 R_BuildNormalizationCube();
6638 r_texture_fogattenuation = NULL;
6639 r_texture_fogheighttexture = NULL;
6640 r_texture_gammaramps = NULL;
6641 //r_texture_fogintensity = NULL;
6642 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6643 memset(&r_waterstate, 0, sizeof(r_waterstate));
6644 r_glsl_permutation = NULL;
6645 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
6646 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
6647 glslshaderstring = NULL;
6649 r_hlsl_permutation = NULL;
6650 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
6651 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
6653 hlslshaderstring = NULL;
6654 memset(&r_svbsp, 0, sizeof (r_svbsp));
6656 r_refdef.fogmasktable_density = 0;
6659 void gl_main_shutdown(void)
6662 R_FrameData_Reset();
6664 R_Main_FreeViewCache();
6666 switch(vid.renderpath)
6668 case RENDERPATH_GL11:
6669 case RENDERPATH_GL13:
6670 case RENDERPATH_GL20:
6671 case RENDERPATH_GLES2:
6673 qglDeleteQueriesARB(r_maxqueries, r_queries);
6675 case RENDERPATH_D3D9:
6676 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6678 case RENDERPATH_D3D10:
6679 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6681 case RENDERPATH_D3D11:
6682 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6684 case RENDERPATH_SOFT:
6690 memset(r_queries, 0, sizeof(r_queries));
6692 r_qwskincache = NULL;
6693 r_qwskincache_size = 0;
6695 // clear out the r_skinframe state
6696 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
6697 memset(&r_skinframe, 0, sizeof(r_skinframe));
6700 Mem_Free(r_svbsp.nodes);
6701 memset(&r_svbsp, 0, sizeof (r_svbsp));
6702 R_FreeTexturePool(&r_main_texturepool);
6703 loadingscreentexture = NULL;
6704 r_texture_blanknormalmap = NULL;
6705 r_texture_white = NULL;
6706 r_texture_grey128 = NULL;
6707 r_texture_black = NULL;
6708 r_texture_whitecube = NULL;
6709 r_texture_normalizationcube = NULL;
6710 r_texture_fogattenuation = NULL;
6711 r_texture_fogheighttexture = NULL;
6712 r_texture_gammaramps = NULL;
6713 r_texture_numcubemaps = 0;
6714 //r_texture_fogintensity = NULL;
6715 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6716 memset(&r_waterstate, 0, sizeof(r_waterstate));
6719 r_glsl_permutation = NULL;
6720 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
6721 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
6722 glslshaderstring = NULL;
6724 r_hlsl_permutation = NULL;
6725 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
6726 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
6728 hlslshaderstring = NULL;
6731 extern void CL_ParseEntityLump(char *entitystring);
6732 void gl_main_newmap(void)
6734 // FIXME: move this code to client
6735 char *entities, entname[MAX_QPATH];
6737 Mem_Free(r_qwskincache);
6738 r_qwskincache = NULL;
6739 r_qwskincache_size = 0;
6742 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
6743 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
6745 CL_ParseEntityLump(entities);
6749 if (cl.worldmodel->brush.entities)
6750 CL_ParseEntityLump(cl.worldmodel->brush.entities);
6752 R_Main_FreeViewCache();
6754 R_FrameData_Reset();
6757 void GL_Main_Init(void)
6759 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
6761 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
6762 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
6763 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
6764 if (gamemode == GAME_NEHAHRA)
6766 Cvar_RegisterVariable (&gl_fogenable);
6767 Cvar_RegisterVariable (&gl_fogdensity);
6768 Cvar_RegisterVariable (&gl_fogred);
6769 Cvar_RegisterVariable (&gl_foggreen);
6770 Cvar_RegisterVariable (&gl_fogblue);
6771 Cvar_RegisterVariable (&gl_fogstart);
6772 Cvar_RegisterVariable (&gl_fogend);
6773 Cvar_RegisterVariable (&gl_skyclip);
6775 Cvar_RegisterVariable(&r_motionblur);
6776 Cvar_RegisterVariable(&r_motionblur_maxblur);
6777 Cvar_RegisterVariable(&r_motionblur_bmin);
6778 Cvar_RegisterVariable(&r_motionblur_vmin);
6779 Cvar_RegisterVariable(&r_motionblur_vmax);
6780 Cvar_RegisterVariable(&r_motionblur_vcoeff);
6781 Cvar_RegisterVariable(&r_motionblur_randomize);
6782 Cvar_RegisterVariable(&r_damageblur);
6783 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
6784 Cvar_RegisterVariable(&r_equalize_entities_minambient);
6785 Cvar_RegisterVariable(&r_equalize_entities_by);
6786 Cvar_RegisterVariable(&r_equalize_entities_to);
6787 Cvar_RegisterVariable(&r_depthfirst);
6788 Cvar_RegisterVariable(&r_useinfinitefarclip);
6789 Cvar_RegisterVariable(&r_farclip_base);
6790 Cvar_RegisterVariable(&r_farclip_world);
6791 Cvar_RegisterVariable(&r_nearclip);
6792 Cvar_RegisterVariable(&r_showbboxes);
6793 Cvar_RegisterVariable(&r_showsurfaces);
6794 Cvar_RegisterVariable(&r_showtris);
6795 Cvar_RegisterVariable(&r_shownormals);
6796 Cvar_RegisterVariable(&r_showlighting);
6797 Cvar_RegisterVariable(&r_showshadowvolumes);
6798 Cvar_RegisterVariable(&r_showcollisionbrushes);
6799 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
6800 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
6801 Cvar_RegisterVariable(&r_showdisabledepthtest);
6802 Cvar_RegisterVariable(&r_drawportals);
6803 Cvar_RegisterVariable(&r_drawentities);
6804 Cvar_RegisterVariable(&r_draw2d);
6805 Cvar_RegisterVariable(&r_drawworld);
6806 Cvar_RegisterVariable(&r_cullentities_trace);
6807 Cvar_RegisterVariable(&r_cullentities_trace_samples);
6808 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
6809 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
6810 Cvar_RegisterVariable(&r_cullentities_trace_delay);
6811 Cvar_RegisterVariable(&r_drawviewmodel);
6812 Cvar_RegisterVariable(&r_drawexteriormodel);
6813 Cvar_RegisterVariable(&r_speeds);
6814 Cvar_RegisterVariable(&r_fullbrights);
6815 Cvar_RegisterVariable(&r_wateralpha);
6816 Cvar_RegisterVariable(&r_dynamic);
6817 Cvar_RegisterVariable(&r_fakelight);
6818 Cvar_RegisterVariable(&r_fakelight_intensity);
6819 Cvar_RegisterVariable(&r_fullbright);
6820 Cvar_RegisterVariable(&r_shadows);
6821 Cvar_RegisterVariable(&r_shadows_darken);
6822 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
6823 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
6824 Cvar_RegisterVariable(&r_shadows_throwdistance);
6825 Cvar_RegisterVariable(&r_shadows_throwdirection);
6826 Cvar_RegisterVariable(&r_shadows_focus);
6827 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
6828 Cvar_RegisterVariable(&r_q1bsp_skymasking);
6829 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
6830 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
6831 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
6832 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
6833 Cvar_RegisterVariable(&r_fog_exp2);
6834 Cvar_RegisterVariable(&r_drawfog);
6835 Cvar_RegisterVariable(&r_transparentdepthmasking);
6836 Cvar_RegisterVariable(&r_texture_dds_load);
6837 Cvar_RegisterVariable(&r_texture_dds_save);
6838 Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
6839 Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
6840 Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
6841 Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
6842 Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
6843 Cvar_RegisterVariable(&r_textureunits);
6844 Cvar_RegisterVariable(&gl_combine);
6845 Cvar_RegisterVariable(&r_glsl);
6846 Cvar_RegisterVariable(&r_glsl_deluxemapping);
6847 Cvar_RegisterVariable(&r_glsl_offsetmapping);
6848 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
6849 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
6850 Cvar_RegisterVariable(&r_glsl_postprocess);
6851 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
6852 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
6853 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
6854 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
6855 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
6856 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
6857 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
6858 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
6860 Cvar_RegisterVariable(&r_water);
6861 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
6862 Cvar_RegisterVariable(&r_water_clippingplanebias);
6863 Cvar_RegisterVariable(&r_water_refractdistort);
6864 Cvar_RegisterVariable(&r_water_reflectdistort);
6865 Cvar_RegisterVariable(&r_water_scissormode);
6866 Cvar_RegisterVariable(&r_lerpsprites);
6867 Cvar_RegisterVariable(&r_lerpmodels);
6868 Cvar_RegisterVariable(&r_lerplightstyles);
6869 Cvar_RegisterVariable(&r_waterscroll);
6870 Cvar_RegisterVariable(&r_bloom);
6871 Cvar_RegisterVariable(&r_bloom_colorscale);
6872 Cvar_RegisterVariable(&r_bloom_brighten);
6873 Cvar_RegisterVariable(&r_bloom_blur);
6874 Cvar_RegisterVariable(&r_bloom_resolution);
6875 Cvar_RegisterVariable(&r_bloom_colorexponent);
6876 Cvar_RegisterVariable(&r_bloom_colorsubtract);
6877 Cvar_RegisterVariable(&r_hdr);
6878 Cvar_RegisterVariable(&r_hdr_scenebrightness);
6879 Cvar_RegisterVariable(&r_hdr_glowintensity);
6880 Cvar_RegisterVariable(&r_hdr_range);
6881 Cvar_RegisterVariable(&r_hdr_irisadaptation);
6882 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
6883 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
6884 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
6885 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
6886 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
6887 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
6888 Cvar_RegisterVariable(&developer_texturelogging);
6889 Cvar_RegisterVariable(&gl_lightmaps);
6890 Cvar_RegisterVariable(&r_test);
6891 Cvar_RegisterVariable(&r_glsl_saturation);
6892 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
6893 Cvar_RegisterVariable(&r_framedatasize);
6894 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
6895 Cvar_SetValue("r_fullbrights", 0);
6896 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
6898 Cvar_RegisterVariable(&r_track_sprites);
6899 Cvar_RegisterVariable(&r_track_sprites_flags);
6900 Cvar_RegisterVariable(&r_track_sprites_scalew);
6901 Cvar_RegisterVariable(&r_track_sprites_scaleh);
6902 Cvar_RegisterVariable(&r_overheadsprites_perspective);
6903 Cvar_RegisterVariable(&r_overheadsprites_pushback);
6904 Cvar_RegisterVariable(&r_overheadsprites_scalex);
6905 Cvar_RegisterVariable(&r_overheadsprites_scaley);
6908 extern void R_Textures_Init(void);
6909 extern void GL_Draw_Init(void);
6910 extern void GL_Main_Init(void);
6911 extern void R_Shadow_Init(void);
6912 extern void R_Sky_Init(void);
6913 extern void GL_Surf_Init(void);
6914 extern void R_Particles_Init(void);
6915 extern void R_Explosion_Init(void);
6916 extern void gl_backend_init(void);
6917 extern void Sbar_Init(void);
6918 extern void R_LightningBeams_Init(void);
6919 extern void Mod_RenderInit(void);
6920 extern void Font_Init(void);
6922 void Render_Init(void)
6935 R_LightningBeams_Init();
6944 extern char *ENGINE_EXTENSIONS;
6947 gl_renderer = (const char *)qglGetString(GL_RENDERER);
6948 gl_vendor = (const char *)qglGetString(GL_VENDOR);
6949 gl_version = (const char *)qglGetString(GL_VERSION);
6950 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
6954 if (!gl_platformextensions)
6955 gl_platformextensions = "";
6957 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
6958 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
6959 Con_Printf("GL_VERSION: %s\n", gl_version);
6960 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
6961 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
6963 VID_CheckExtensions();
6965 // LordHavoc: report supported extensions
6966 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
6968 // clear to black (loading plaque will be seen over this)
6969 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6972 int R_CullBox(const vec3_t mins, const vec3_t maxs)
6976 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
6978 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
6981 p = r_refdef.view.frustum + i;
6986 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6990 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6994 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6998 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7002 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7006 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7010 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7014 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7022 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
7026 for (i = 0;i < numplanes;i++)
7033 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7037 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7041 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7045 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7049 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7053 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7057 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7061 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7069 //==================================================================================
7071 // LordHavoc: this stores temporary data used within the same frame
7073 typedef struct r_framedata_mem_s
7075 struct r_framedata_mem_s *purge; // older mem block to free on next frame
7076 size_t size; // how much usable space
7077 size_t current; // how much space in use
7078 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
7079 size_t wantedsize; // how much space was allocated
7080 unsigned char *data; // start of real data (16byte aligned)
7084 static r_framedata_mem_t *r_framedata_mem;
7086 void R_FrameData_Reset(void)
7088 while (r_framedata_mem)
7090 r_framedata_mem_t *next = r_framedata_mem->purge;
7091 Mem_Free(r_framedata_mem);
7092 r_framedata_mem = next;
7096 void R_FrameData_Resize(void)
7099 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
7100 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
7101 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
7103 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
7104 newmem->wantedsize = wantedsize;
7105 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
7106 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
7107 newmem->current = 0;
7109 newmem->purge = r_framedata_mem;
7110 r_framedata_mem = newmem;
7114 void R_FrameData_NewFrame(void)
7116 R_FrameData_Resize();
7117 if (!r_framedata_mem)
7119 // if we ran out of space on the last frame, free the old memory now
7120 while (r_framedata_mem->purge)
7122 // repeatedly remove the second item in the list, leaving only head
7123 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
7124 Mem_Free(r_framedata_mem->purge);
7125 r_framedata_mem->purge = next;
7127 // reset the current mem pointer
7128 r_framedata_mem->current = 0;
7129 r_framedata_mem->mark = 0;
7132 void *R_FrameData_Alloc(size_t size)
7136 // align to 16 byte boundary - the data pointer is already aligned, so we
7137 // only need to ensure the size of every allocation is also aligned
7138 size = (size + 15) & ~15;
7140 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
7142 // emergency - we ran out of space, allocate more memory
7143 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
7144 R_FrameData_Resize();
7147 data = r_framedata_mem->data + r_framedata_mem->current;
7148 r_framedata_mem->current += size;
7150 // count the usage for stats
7151 r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
7152 r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
7154 return (void *)data;
7157 void *R_FrameData_Store(size_t size, void *data)
7159 void *d = R_FrameData_Alloc(size);
7161 memcpy(d, data, size);
7165 void R_FrameData_SetMark(void)
7167 if (!r_framedata_mem)
7169 r_framedata_mem->mark = r_framedata_mem->current;
7172 void R_FrameData_ReturnToMark(void)
7174 if (!r_framedata_mem)
7176 r_framedata_mem->current = r_framedata_mem->mark;
7179 //==================================================================================
7181 // LordHavoc: animcache originally written by Echon, rewritten since then
7184 * Animation cache prevents re-generating mesh data for an animated model
7185 * multiple times in one frame for lighting, shadowing, reflections, etc.
7188 void R_AnimCache_Free(void)
7192 void R_AnimCache_ClearCache(void)
7195 entity_render_t *ent;
7197 for (i = 0;i < r_refdef.scene.numentities;i++)
7199 ent = r_refdef.scene.entities[i];
7200 ent->animcache_vertex3f = NULL;
7201 ent->animcache_normal3f = NULL;
7202 ent->animcache_svector3f = NULL;
7203 ent->animcache_tvector3f = NULL;
7204 ent->animcache_vertexmesh = NULL;
7205 ent->animcache_vertex3fbuffer = NULL;
7206 ent->animcache_vertexmeshbuffer = NULL;
7210 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
7214 // check if we need the meshbuffers
7215 if (!vid.useinterleavedarrays)
7218 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
7219 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
7220 // TODO: upload vertex3f buffer?
7221 if (ent->animcache_vertexmesh)
7223 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
7224 for (i = 0;i < numvertices;i++)
7225 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7226 if (ent->animcache_svector3f)
7227 for (i = 0;i < numvertices;i++)
7228 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
7229 if (ent->animcache_tvector3f)
7230 for (i = 0;i < numvertices;i++)
7231 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
7232 if (ent->animcache_normal3f)
7233 for (i = 0;i < numvertices;i++)
7234 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
7235 // TODO: upload vertexmeshbuffer?
7239 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
7241 dp_model_t *model = ent->model;
7243 // see if it's already cached this frame
7244 if (ent->animcache_vertex3f)
7246 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
7247 if (wantnormals || wanttangents)
7249 if (ent->animcache_normal3f)
7250 wantnormals = false;
7251 if (ent->animcache_svector3f)
7252 wanttangents = false;
7253 if (wantnormals || wanttangents)
7255 numvertices = model->surfmesh.num_vertices;
7257 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7260 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7261 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7263 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
7264 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7270 // see if this ent is worth caching
7271 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
7273 // get some memory for this entity and generate mesh data
7274 numvertices = model->surfmesh.num_vertices;
7275 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7277 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7280 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7281 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7283 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
7284 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7289 void R_AnimCache_CacheVisibleEntities(void)
7292 qboolean wantnormals = true;
7293 qboolean wanttangents = !r_showsurfaces.integer;
7295 switch(vid.renderpath)
7297 case RENDERPATH_GL20:
7298 case RENDERPATH_D3D9:
7299 case RENDERPATH_D3D10:
7300 case RENDERPATH_D3D11:
7301 case RENDERPATH_GLES2:
7303 case RENDERPATH_GL13:
7304 case RENDERPATH_GL11:
7305 wanttangents = false;
7307 case RENDERPATH_SOFT:
7311 if (r_shownormals.integer)
7312 wanttangents = wantnormals = true;
7314 // TODO: thread this
7315 // NOTE: R_PrepareRTLights() also caches entities
7317 for (i = 0;i < r_refdef.scene.numentities;i++)
7318 if (r_refdef.viewcache.entityvisible[i])
7319 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
7322 //==================================================================================
7324 static void R_View_UpdateEntityLighting (void)
7327 entity_render_t *ent;
7328 vec3_t tempdiffusenormal, avg;
7329 vec_t f, fa, fd, fdd;
7330 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
7332 for (i = 0;i < r_refdef.scene.numentities;i++)
7334 ent = r_refdef.scene.entities[i];
7336 // skip unseen models
7337 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
7341 if (ent->model && ent->model->brush.num_leafs)
7343 // TODO: use modellight for r_ambient settings on world?
7344 VectorSet(ent->modellight_ambient, 0, 0, 0);
7345 VectorSet(ent->modellight_diffuse, 0, 0, 0);
7346 VectorSet(ent->modellight_lightdir, 0, 0, 1);
7350 // fetch the lighting from the worldmodel data
7351 VectorClear(ent->modellight_ambient);
7352 VectorClear(ent->modellight_diffuse);
7353 VectorClear(tempdiffusenormal);
7354 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
7357 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7359 // complete lightning for lit sprites
7360 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
7361 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
7363 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
7364 org[2] = org[2] + r_overheadsprites_pushback.value;
7365 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
7368 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
7370 if(ent->flags & RENDER_EQUALIZE)
7372 // first fix up ambient lighting...
7373 if(r_equalize_entities_minambient.value > 0)
7375 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7378 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
7379 if(fa < r_equalize_entities_minambient.value * fd)
7382 // fa'/fd' = minambient
7383 // fa'+0.25*fd' = fa+0.25*fd
7385 // fa' = fd' * minambient
7386 // fd'*(0.25+minambient) = fa+0.25*fd
7388 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
7389 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
7391 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
7392 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
7393 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
7394 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7399 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
7401 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
7402 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7406 // adjust brightness and saturation to target
7407 avg[0] = avg[1] = avg[2] = fa / f;
7408 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
7409 avg[0] = avg[1] = avg[2] = fd / f;
7410 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
7416 VectorSet(ent->modellight_ambient, 1, 1, 1);
7418 // move the light direction into modelspace coordinates for lighting code
7419 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
7420 if(VectorLength2(ent->modellight_lightdir) == 0)
7421 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
7422 VectorNormalize(ent->modellight_lightdir);
7426 #define MAX_LINEOFSIGHTTRACES 64
7428 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
7431 vec3_t boxmins, boxmaxs;
7434 dp_model_t *model = r_refdef.scene.worldmodel;
7436 if (!model || !model->brush.TraceLineOfSight)
7439 // expand the box a little
7440 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
7441 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
7442 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
7443 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
7444 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
7445 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
7447 // return true if eye is inside enlarged box
7448 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
7452 VectorCopy(eye, start);
7453 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
7454 if (model->brush.TraceLineOfSight(model, start, end))
7457 // try various random positions
7458 for (i = 0;i < numsamples;i++)
7460 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
7461 if (model->brush.TraceLineOfSight(model, start, end))
7469 static void R_View_UpdateEntityVisible (void)
7474 entity_render_t *ent;
7476 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7477 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7478 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
7479 : RENDER_EXTERIORMODEL;
7480 if (!r_drawviewmodel.integer)
7481 renderimask |= RENDER_VIEWMODEL;
7482 if (!r_drawexteriormodel.integer)
7483 renderimask |= RENDER_EXTERIORMODEL;
7484 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
7486 // worldmodel can check visibility
7487 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
7488 for (i = 0;i < r_refdef.scene.numentities;i++)
7490 ent = r_refdef.scene.entities[i];
7491 if (!(ent->flags & renderimask))
7492 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)))
7493 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))
7494 r_refdef.viewcache.entityvisible[i] = true;
7496 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
7497 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
7499 for (i = 0;i < r_refdef.scene.numentities;i++)
7501 ent = r_refdef.scene.entities[i];
7502 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
7504 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
7506 continue; // temp entities do pvs only
7507 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
7508 ent->last_trace_visibility = realtime;
7509 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
7510 r_refdef.viewcache.entityvisible[i] = 0;
7517 // no worldmodel or it can't check visibility
7518 for (i = 0;i < r_refdef.scene.numentities;i++)
7520 ent = r_refdef.scene.entities[i];
7521 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));
7526 /// only used if skyrendermasked, and normally returns false
7527 int R_DrawBrushModelsSky (void)
7530 entity_render_t *ent;
7533 for (i = 0;i < r_refdef.scene.numentities;i++)
7535 if (!r_refdef.viewcache.entityvisible[i])
7537 ent = r_refdef.scene.entities[i];
7538 if (!ent->model || !ent->model->DrawSky)
7540 ent->model->DrawSky(ent);
7546 static void R_DrawNoModel(entity_render_t *ent);
7547 static void R_DrawModels(void)
7550 entity_render_t *ent;
7552 for (i = 0;i < r_refdef.scene.numentities;i++)
7554 if (!r_refdef.viewcache.entityvisible[i])
7556 ent = r_refdef.scene.entities[i];
7557 r_refdef.stats.entities++;
7558 if (ent->model && ent->model->Draw != NULL)
7559 ent->model->Draw(ent);
7565 static void R_DrawModelsDepth(void)
7568 entity_render_t *ent;
7570 for (i = 0;i < r_refdef.scene.numentities;i++)
7572 if (!r_refdef.viewcache.entityvisible[i])
7574 ent = r_refdef.scene.entities[i];
7575 if (ent->model && ent->model->DrawDepth != NULL)
7576 ent->model->DrawDepth(ent);
7580 static void R_DrawModelsDebug(void)
7583 entity_render_t *ent;
7585 for (i = 0;i < r_refdef.scene.numentities;i++)
7587 if (!r_refdef.viewcache.entityvisible[i])
7589 ent = r_refdef.scene.entities[i];
7590 if (ent->model && ent->model->DrawDebug != NULL)
7591 ent->model->DrawDebug(ent);
7595 static void R_DrawModelsAddWaterPlanes(void)
7598 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->DrawAddWaterPlanes != NULL)
7606 ent->model->DrawAddWaterPlanes(ent);
7610 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
7612 if (r_hdr_irisadaptation.integer)
7616 vec3_t diffusenormal;
7621 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
7622 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
7623 brightness = max(0.0000001f, brightness);
7624 goal = r_hdr_irisadaptation_multiplier.value / brightness;
7625 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
7626 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
7627 current = r_hdr_irisadaptation_value.value;
7629 current = min(current + adjust, goal);
7630 else if (current > goal)
7631 current = max(current - adjust, goal);
7632 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
7633 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
7635 else if (r_hdr_irisadaptation_value.value != 1.0f)
7636 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
7639 static void R_View_SetFrustum(const int *scissor)
7642 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
7643 vec3_t forward, left, up, origin, v;
7647 // flipped x coordinates (because x points left here)
7648 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
7649 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
7651 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
7652 switch(vid.renderpath)
7654 case RENDERPATH_D3D9:
7655 case RENDERPATH_D3D10:
7656 case RENDERPATH_D3D11:
7657 case RENDERPATH_SOFT:
7658 // non-flipped y coordinates
7659 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
7660 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
7662 case RENDERPATH_GL11:
7663 case RENDERPATH_GL13:
7664 case RENDERPATH_GL20:
7665 case RENDERPATH_GLES2:
7666 // non-flipped y coordinates
7667 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
7668 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
7673 // we can't trust r_refdef.view.forward and friends in reflected scenes
7674 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
7677 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
7678 r_refdef.view.frustum[0].normal[1] = 0 - 0;
7679 r_refdef.view.frustum[0].normal[2] = -1 - 0;
7680 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
7681 r_refdef.view.frustum[1].normal[1] = 0 + 0;
7682 r_refdef.view.frustum[1].normal[2] = -1 + 0;
7683 r_refdef.view.frustum[2].normal[0] = 0 - 0;
7684 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
7685 r_refdef.view.frustum[2].normal[2] = -1 - 0;
7686 r_refdef.view.frustum[3].normal[0] = 0 + 0;
7687 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
7688 r_refdef.view.frustum[3].normal[2] = -1 + 0;
7692 zNear = r_refdef.nearclip;
7693 nudge = 1.0 - 1.0 / (1<<23);
7694 r_refdef.view.frustum[4].normal[0] = 0 - 0;
7695 r_refdef.view.frustum[4].normal[1] = 0 - 0;
7696 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
7697 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
7698 r_refdef.view.frustum[5].normal[0] = 0 + 0;
7699 r_refdef.view.frustum[5].normal[1] = 0 + 0;
7700 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
7701 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
7707 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
7708 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
7709 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
7710 r_refdef.view.frustum[0].dist = m[15] - m[12];
7712 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
7713 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
7714 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
7715 r_refdef.view.frustum[1].dist = m[15] + m[12];
7717 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
7718 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
7719 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
7720 r_refdef.view.frustum[2].dist = m[15] - m[13];
7722 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
7723 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
7724 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
7725 r_refdef.view.frustum[3].dist = m[15] + m[13];
7727 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
7728 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
7729 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
7730 r_refdef.view.frustum[4].dist = m[15] - m[14];
7732 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
7733 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
7734 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
7735 r_refdef.view.frustum[5].dist = m[15] + m[14];
7738 if (r_refdef.view.useperspective)
7740 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
7741 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]);
7742 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]);
7743 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]);
7744 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]);
7746 // then the normals from the corners relative to origin
7747 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
7748 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
7749 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
7750 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
7752 // in a NORMAL view, forward cross left == up
7753 // in a REFLECTED view, forward cross left == down
7754 // so our cross products above need to be adjusted for a left handed coordinate system
7755 CrossProduct(forward, left, v);
7756 if(DotProduct(v, up) < 0)
7758 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
7759 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
7760 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
7761 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
7764 // Leaving those out was a mistake, those were in the old code, and they
7765 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
7766 // I couldn't reproduce it after adding those normalizations. --blub
7767 VectorNormalize(r_refdef.view.frustum[0].normal);
7768 VectorNormalize(r_refdef.view.frustum[1].normal);
7769 VectorNormalize(r_refdef.view.frustum[2].normal);
7770 VectorNormalize(r_refdef.view.frustum[3].normal);
7772 // make the corners absolute
7773 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
7774 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
7775 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
7776 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
7779 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7781 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
7782 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
7783 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
7784 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
7785 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7789 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
7790 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
7791 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
7792 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
7793 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7794 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
7795 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
7796 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
7797 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
7798 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7800 r_refdef.view.numfrustumplanes = 5;
7802 if (r_refdef.view.useclipplane)
7804 r_refdef.view.numfrustumplanes = 6;
7805 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
7808 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7809 PlaneClassify(r_refdef.view.frustum + i);
7811 // LordHavoc: note to all quake engine coders, Quake had a special case
7812 // for 90 degrees which assumed a square view (wrong), so I removed it,
7813 // Quake2 has it disabled as well.
7815 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
7816 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
7817 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
7818 //PlaneClassify(&frustum[0]);
7820 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
7821 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
7822 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
7823 //PlaneClassify(&frustum[1]);
7825 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
7826 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
7827 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
7828 //PlaneClassify(&frustum[2]);
7830 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
7831 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
7832 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
7833 //PlaneClassify(&frustum[3]);
7836 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
7837 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
7838 //PlaneClassify(&frustum[4]);
7841 void R_View_UpdateWithScissor(const int *myscissor)
7843 R_Main_ResizeViewCache();
7844 R_View_SetFrustum(myscissor);
7845 R_View_WorldVisibility(r_refdef.view.useclipplane);
7846 R_View_UpdateEntityVisible();
7847 R_View_UpdateEntityLighting();
7850 void R_View_Update(void)
7852 R_Main_ResizeViewCache();
7853 R_View_SetFrustum(NULL);
7854 R_View_WorldVisibility(r_refdef.view.useclipplane);
7855 R_View_UpdateEntityVisible();
7856 R_View_UpdateEntityLighting();
7859 void R_SetupView(qboolean allowwaterclippingplane)
7861 const float *customclipplane = NULL;
7863 if (r_refdef.view.useclipplane && allowwaterclippingplane)
7865 // LordHavoc: couldn't figure out how to make this approach the
7866 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
7867 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
7868 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
7869 dist = r_refdef.view.clipplane.dist;
7870 plane[0] = r_refdef.view.clipplane.normal[0];
7871 plane[1] = r_refdef.view.clipplane.normal[1];
7872 plane[2] = r_refdef.view.clipplane.normal[2];
7874 customclipplane = plane;
7877 if (!r_refdef.view.useperspective)
7878 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);
7879 else if (vid.stencil && r_useinfinitefarclip.integer)
7880 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);
7882 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);
7883 R_SetViewport(&r_refdef.view.viewport);
7886 void R_EntityMatrix(const matrix4x4_t *matrix)
7888 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
7890 gl_modelmatrixchanged = false;
7891 gl_modelmatrix = *matrix;
7892 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
7893 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
7894 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
7895 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
7897 switch(vid.renderpath)
7899 case RENDERPATH_D3D9:
7901 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
7902 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
7905 case RENDERPATH_D3D10:
7906 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
7908 case RENDERPATH_D3D11:
7909 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
7911 case RENDERPATH_GL13:
7912 case RENDERPATH_GL11:
7913 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7915 case RENDERPATH_SOFT:
7916 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
7917 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
7919 case RENDERPATH_GL20:
7920 case RENDERPATH_GLES2:
7921 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
7922 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
7928 void R_ResetViewRendering2D(void)
7930 r_viewport_t viewport;
7933 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
7934 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);
7935 R_SetViewport(&viewport);
7936 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
7937 GL_Color(1, 1, 1, 1);
7938 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7939 GL_BlendFunc(GL_ONE, GL_ZERO);
7940 GL_ScissorTest(false);
7941 GL_DepthMask(false);
7942 GL_DepthRange(0, 1);
7943 GL_DepthTest(false);
7944 GL_DepthFunc(GL_LEQUAL);
7945 R_EntityMatrix(&identitymatrix);
7946 R_Mesh_ResetTextureState();
7947 GL_PolygonOffset(0, 0);
7948 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
7949 switch(vid.renderpath)
7951 case RENDERPATH_GL11:
7952 case RENDERPATH_GL13:
7953 case RENDERPATH_GL20:
7954 case RENDERPATH_GLES2:
7955 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
7957 case RENDERPATH_D3D9:
7958 case RENDERPATH_D3D10:
7959 case RENDERPATH_D3D11:
7960 case RENDERPATH_SOFT:
7963 GL_CullFace(GL_NONE);
7966 void R_ResetViewRendering3D(void)
7971 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
7972 GL_Color(1, 1, 1, 1);
7973 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7974 GL_BlendFunc(GL_ONE, GL_ZERO);
7975 GL_ScissorTest(true);
7977 GL_DepthRange(0, 1);
7979 GL_DepthFunc(GL_LEQUAL);
7980 R_EntityMatrix(&identitymatrix);
7981 R_Mesh_ResetTextureState();
7982 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7983 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
7984 switch(vid.renderpath)
7986 case RENDERPATH_GL11:
7987 case RENDERPATH_GL13:
7988 case RENDERPATH_GL20:
7989 case RENDERPATH_GLES2:
7990 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
7992 case RENDERPATH_D3D9:
7993 case RENDERPATH_D3D10:
7994 case RENDERPATH_D3D11:
7995 case RENDERPATH_SOFT:
7998 GL_CullFace(r_refdef.view.cullface_back);
8003 R_RenderView_UpdateViewVectors
8006 static void R_RenderView_UpdateViewVectors(void)
8008 // break apart the view matrix into vectors for various purposes
8009 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
8010 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
8011 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
8012 VectorNegate(r_refdef.view.left, r_refdef.view.right);
8013 // make an inverted copy of the view matrix for tracking sprites
8014 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
8017 void R_RenderScene(void);
8018 void R_RenderWaterPlanes(void);
8020 static void R_Water_StartFrame(void)
8023 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
8024 r_waterstate_waterplane_t *p;
8026 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
8029 switch(vid.renderpath)
8031 case RENDERPATH_GL20:
8032 case RENDERPATH_D3D9:
8033 case RENDERPATH_D3D10:
8034 case RENDERPATH_D3D11:
8035 case RENDERPATH_SOFT:
8036 case RENDERPATH_GLES2:
8038 case RENDERPATH_GL13:
8039 case RENDERPATH_GL11:
8043 // set waterwidth and waterheight to the water resolution that will be
8044 // used (often less than the screen resolution for faster rendering)
8045 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
8046 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
8048 // calculate desired texture sizes
8049 // can't use water if the card does not support the texture size
8050 if (!r_water.integer || r_showsurfaces.integer)
8051 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
8052 else if (vid.support.arb_texture_non_power_of_two)
8054 texturewidth = waterwidth;
8055 textureheight = waterheight;
8056 camerawidth = waterwidth;
8057 cameraheight = waterheight;
8061 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
8062 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
8063 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
8064 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
8067 // allocate textures as needed
8068 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
8070 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8071 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
8073 if (p->texture_refraction)
8074 R_FreeTexture(p->texture_refraction);
8075 p->texture_refraction = NULL;
8076 if (p->texture_reflection)
8077 R_FreeTexture(p->texture_reflection);
8078 p->texture_reflection = NULL;
8079 if (p->texture_camera)
8080 R_FreeTexture(p->texture_camera);
8081 p->texture_camera = NULL;
8083 memset(&r_waterstate, 0, sizeof(r_waterstate));
8084 r_waterstate.texturewidth = texturewidth;
8085 r_waterstate.textureheight = textureheight;
8086 r_waterstate.camerawidth = camerawidth;
8087 r_waterstate.cameraheight = cameraheight;
8090 if (r_waterstate.texturewidth)
8092 r_waterstate.enabled = true;
8094 // when doing a reduced render (HDR) we want to use a smaller area
8095 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
8096 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
8098 // set up variables that will be used in shader setup
8099 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8100 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8101 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8102 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8105 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8106 r_waterstate.numwaterplanes = 0;
8109 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
8111 int triangleindex, planeindex;
8117 r_waterstate_waterplane_t *p;
8118 texture_t *t = R_GetCurrentTexture(surface->texture);
8120 // just use the first triangle with a valid normal for any decisions
8121 VectorClear(normal);
8122 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
8124 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
8125 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
8126 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
8127 TriangleNormal(vert[0], vert[1], vert[2], normal);
8128 if (VectorLength2(normal) >= 0.001)
8132 VectorCopy(normal, plane.normal);
8133 VectorNormalize(plane.normal);
8134 plane.dist = DotProduct(vert[0], plane.normal);
8135 PlaneClassify(&plane);
8136 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
8138 // skip backfaces (except if nocullface is set)
8139 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
8141 VectorNegate(plane.normal, plane.normal);
8143 PlaneClassify(&plane);
8147 // find a matching plane if there is one
8148 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8149 if(p->camera_entity == t->camera_entity)
8150 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
8152 if (planeindex >= r_waterstate.maxwaterplanes)
8153 return; // nothing we can do, out of planes
8155 // if this triangle does not fit any known plane rendered this frame, add one
8156 if (planeindex >= r_waterstate.numwaterplanes)
8158 // store the new plane
8159 r_waterstate.numwaterplanes++;
8161 // clear materialflags and pvs
8162 p->materialflags = 0;
8163 p->pvsvalid = false;
8164 p->camera_entity = t->camera_entity;
8165 VectorCopy(surface->mins, p->mins);
8166 VectorCopy(surface->maxs, p->maxs);
8171 p->mins[0] = min(p->mins[0], surface->mins[0]);
8172 p->mins[1] = min(p->mins[1], surface->mins[1]);
8173 p->mins[2] = min(p->mins[2], surface->mins[2]);
8174 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
8175 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
8176 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
8178 // merge this surface's materialflags into the waterplane
8179 p->materialflags |= t->currentmaterialflags;
8180 if(!(p->materialflags & MATERIALFLAG_CAMERA))
8182 // merge this surface's PVS into the waterplane
8183 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
8184 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
8185 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
8187 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
8193 static void R_Water_ProcessPlanes(void)
8196 r_refdef_view_t originalview;
8197 r_refdef_view_t myview;
8199 r_waterstate_waterplane_t *p;
8202 originalview = r_refdef.view;
8204 // make sure enough textures are allocated
8205 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8207 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8209 if (!p->texture_refraction)
8210 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);
8211 if (!p->texture_refraction)
8214 else if (p->materialflags & MATERIALFLAG_CAMERA)
8216 if (!p->texture_camera)
8217 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);
8218 if (!p->texture_camera)
8222 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8224 if (!p->texture_reflection)
8225 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);
8226 if (!p->texture_reflection)
8232 r_refdef.view = originalview;
8233 r_refdef.view.showdebug = false;
8234 r_refdef.view.width = r_waterstate.waterwidth;
8235 r_refdef.view.height = r_waterstate.waterheight;
8236 r_refdef.view.useclipplane = true;
8237 myview = r_refdef.view;
8238 r_waterstate.renderingscene = true;
8239 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8241 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8243 r_refdef.view = myview;
8244 if(r_water_scissormode.integer)
8247 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8248 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8251 // render reflected scene and copy into texture
8252 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
8253 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
8254 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
8255 r_refdef.view.clipplane = p->plane;
8257 // reverse the cullface settings for this render
8258 r_refdef.view.cullface_front = GL_FRONT;
8259 r_refdef.view.cullface_back = GL_BACK;
8260 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
8262 r_refdef.view.usecustompvs = true;
8264 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8266 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8269 R_ResetViewRendering3D();
8270 R_ClearScreen(r_refdef.fogenabled);
8271 if(r_water_scissormode.integer & 2)
8272 R_View_UpdateWithScissor(myscissor);
8275 if(r_water_scissormode.integer & 1)
8276 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8279 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);
8282 // render the normal view scene and copy into texture
8283 // (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)
8284 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8286 r_refdef.view = myview;
8287 if(r_water_scissormode.integer)
8290 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8291 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8294 r_waterstate.renderingrefraction = true;
8296 r_refdef.view.clipplane = p->plane;
8297 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8298 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8300 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
8302 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8303 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
8304 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8305 R_RenderView_UpdateViewVectors();
8306 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8308 r_refdef.view.usecustompvs = true;
8309 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);
8313 PlaneClassify(&r_refdef.view.clipplane);
8315 R_ResetViewRendering3D();
8316 R_ClearScreen(r_refdef.fogenabled);
8317 if(r_water_scissormode.integer & 2)
8318 R_View_UpdateWithScissor(myscissor);
8321 if(r_water_scissormode.integer & 1)
8322 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8325 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);
8326 r_waterstate.renderingrefraction = false;
8328 else if (p->materialflags & MATERIALFLAG_CAMERA)
8330 r_refdef.view = myview;
8332 r_refdef.view.clipplane = p->plane;
8333 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8334 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8336 r_refdef.view.width = r_waterstate.camerawidth;
8337 r_refdef.view.height = r_waterstate.cameraheight;
8338 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
8339 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
8341 if(p->camera_entity)
8343 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8344 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8347 // note: all of the view is used for displaying... so
8348 // there is no use in scissoring
8350 // reverse the cullface settings for this render
8351 r_refdef.view.cullface_front = GL_FRONT;
8352 r_refdef.view.cullface_back = GL_BACK;
8353 // also reverse the view matrix
8354 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
8355 R_RenderView_UpdateViewVectors();
8356 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8358 r_refdef.view.usecustompvs = true;
8359 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);
8362 // camera needs no clipplane
8363 r_refdef.view.useclipplane = false;
8365 PlaneClassify(&r_refdef.view.clipplane);
8367 R_ResetViewRendering3D();
8368 R_ClearScreen(r_refdef.fogenabled);
8372 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);
8373 r_waterstate.renderingrefraction = false;
8377 r_waterstate.renderingscene = false;
8378 r_refdef.view = originalview;
8379 R_ResetViewRendering3D();
8380 R_ClearScreen(r_refdef.fogenabled);
8384 r_refdef.view = originalview;
8385 r_waterstate.renderingscene = false;
8386 Cvar_SetValueQuick(&r_water, 0);
8387 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
8391 void R_Bloom_StartFrame(void)
8393 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
8395 switch(vid.renderpath)
8397 case RENDERPATH_GL20:
8398 case RENDERPATH_D3D9:
8399 case RENDERPATH_D3D10:
8400 case RENDERPATH_D3D11:
8401 case RENDERPATH_SOFT:
8402 case RENDERPATH_GLES2:
8404 case RENDERPATH_GL13:
8405 case RENDERPATH_GL11:
8409 // set bloomwidth and bloomheight to the bloom resolution that will be
8410 // used (often less than the screen resolution for faster rendering)
8411 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
8412 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
8413 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
8414 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
8415 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
8417 // calculate desired texture sizes
8418 if (vid.support.arb_texture_non_power_of_two)
8420 screentexturewidth = r_refdef.view.width;
8421 screentextureheight = r_refdef.view.height;
8422 bloomtexturewidth = r_bloomstate.bloomwidth;
8423 bloomtextureheight = r_bloomstate.bloomheight;
8427 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
8428 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
8429 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
8430 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
8433 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))
8435 Cvar_SetValueQuick(&r_hdr, 0);
8436 Cvar_SetValueQuick(&r_bloom, 0);
8437 Cvar_SetValueQuick(&r_motionblur, 0);
8438 Cvar_SetValueQuick(&r_damageblur, 0);
8441 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)))
8442 screentexturewidth = screentextureheight = 0;
8443 if (!r_hdr.integer && !r_bloom.integer)
8444 bloomtexturewidth = bloomtextureheight = 0;
8446 // allocate textures as needed
8447 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
8449 if (r_bloomstate.texture_screen)
8450 R_FreeTexture(r_bloomstate.texture_screen);
8451 r_bloomstate.texture_screen = NULL;
8452 r_bloomstate.screentexturewidth = screentexturewidth;
8453 r_bloomstate.screentextureheight = screentextureheight;
8454 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
8455 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);
8457 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
8459 if (r_bloomstate.texture_bloom)
8460 R_FreeTexture(r_bloomstate.texture_bloom);
8461 r_bloomstate.texture_bloom = NULL;
8462 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
8463 r_bloomstate.bloomtextureheight = bloomtextureheight;
8464 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
8465 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);
8468 // when doing a reduced render (HDR) we want to use a smaller area
8469 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
8470 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
8471 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
8472 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
8473 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
8475 // set up a texcoord array for the full resolution screen image
8476 // (we have to keep this around to copy back during final render)
8477 r_bloomstate.screentexcoord2f[0] = 0;
8478 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
8479 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
8480 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
8481 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
8482 r_bloomstate.screentexcoord2f[5] = 0;
8483 r_bloomstate.screentexcoord2f[6] = 0;
8484 r_bloomstate.screentexcoord2f[7] = 0;
8486 // set up a texcoord array for the reduced resolution bloom image
8487 // (which will be additive blended over the screen image)
8488 r_bloomstate.bloomtexcoord2f[0] = 0;
8489 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8490 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8491 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8492 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8493 r_bloomstate.bloomtexcoord2f[5] = 0;
8494 r_bloomstate.bloomtexcoord2f[6] = 0;
8495 r_bloomstate.bloomtexcoord2f[7] = 0;
8497 switch(vid.renderpath)
8499 case RENDERPATH_GL11:
8500 case RENDERPATH_GL13:
8501 case RENDERPATH_GL20:
8502 case RENDERPATH_SOFT:
8503 case RENDERPATH_GLES2:
8505 case RENDERPATH_D3D9:
8506 case RENDERPATH_D3D10:
8507 case RENDERPATH_D3D11:
8510 for (i = 0;i < 4;i++)
8512 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
8513 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
8514 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
8515 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
8521 if (r_hdr.integer || r_bloom.integer)
8523 r_bloomstate.enabled = true;
8524 r_bloomstate.hdr = r_hdr.integer != 0;
8527 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);
8530 void R_Bloom_CopyBloomTexture(float colorscale)
8532 r_refdef.stats.bloom++;
8534 // scale down screen texture to the bloom texture size
8536 R_SetViewport(&r_bloomstate.viewport);
8537 GL_BlendFunc(GL_ONE, GL_ZERO);
8538 GL_Color(colorscale, colorscale, colorscale, 1);
8539 // 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...
8540 switch(vid.renderpath)
8542 case RENDERPATH_GL11:
8543 case RENDERPATH_GL13:
8544 case RENDERPATH_GL20:
8545 case RENDERPATH_SOFT:
8546 case RENDERPATH_GLES2:
8547 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8549 case RENDERPATH_D3D9:
8550 case RENDERPATH_D3D10:
8551 case RENDERPATH_D3D11:
8552 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8555 // TODO: do boxfilter scale-down in shader?
8556 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
8557 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8558 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8560 // we now have a bloom image in the framebuffer
8561 // copy it into the bloom image texture for later processing
8562 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);
8563 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8566 void R_Bloom_CopyHDRTexture(void)
8568 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);
8569 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8572 void R_Bloom_MakeTexture(void)
8575 float xoffset, yoffset, r, brighten;
8577 r_refdef.stats.bloom++;
8579 R_ResetViewRendering2D();
8581 // we have a bloom image in the framebuffer
8583 R_SetViewport(&r_bloomstate.viewport);
8585 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
8588 r = bound(0, r_bloom_colorexponent.value / x, 1);
8589 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
8591 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
8592 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
8593 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8594 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8596 // copy the vertically blurred bloom view to a texture
8597 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);
8598 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8601 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
8602 brighten = r_bloom_brighten.value;
8604 brighten *= r_hdr_range.value;
8605 brighten = sqrt(brighten);
8607 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
8608 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
8610 for (dir = 0;dir < 2;dir++)
8612 // blend on at multiple vertical offsets to achieve a vertical blur
8613 // TODO: do offset blends using GLSL
8614 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
8615 GL_BlendFunc(GL_ONE, GL_ZERO);
8616 for (x = -range;x <= range;x++)
8618 if (!dir){xoffset = 0;yoffset = x;}
8619 else {xoffset = x;yoffset = 0;}
8620 xoffset /= (float)r_bloomstate.bloomtexturewidth;
8621 yoffset /= (float)r_bloomstate.bloomtextureheight;
8622 // compute a texcoord array with the specified x and y offset
8623 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
8624 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8625 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8626 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8627 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8628 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
8629 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
8630 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
8631 // this r value looks like a 'dot' particle, fading sharply to
8632 // black at the edges
8633 // (probably not realistic but looks good enough)
8634 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
8635 //r = brighten/(range*2+1);
8636 r = brighten / (range * 2 + 1);
8638 r *= (1 - x*x/(float)(range*range));
8639 GL_Color(r, r, r, 1);
8640 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
8641 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8642 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8643 GL_BlendFunc(GL_ONE, GL_ONE);
8646 // copy the vertically blurred bloom view to a texture
8647 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);
8648 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8652 void R_HDR_RenderBloomTexture(void)
8654 int oldwidth, oldheight;
8655 float oldcolorscale;
8656 qboolean oldwaterstate;
8658 oldwaterstate = r_waterstate.enabled;
8659 oldcolorscale = r_refdef.view.colorscale;
8660 oldwidth = r_refdef.view.width;
8661 oldheight = r_refdef.view.height;
8662 r_refdef.view.width = r_bloomstate.bloomwidth;
8663 r_refdef.view.height = r_bloomstate.bloomheight;
8665 if(r_hdr.integer < 2)
8666 r_waterstate.enabled = false;
8668 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
8669 // TODO: add exposure compensation features
8670 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
8672 r_refdef.view.showdebug = false;
8673 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
8675 R_ResetViewRendering3D();
8677 R_ClearScreen(r_refdef.fogenabled);
8678 if (r_timereport_active)
8679 R_TimeReport("HDRclear");
8682 if (r_timereport_active)
8683 R_TimeReport("visibility");
8685 // only do secondary renders with HDR if r_hdr is 2 or higher
8686 r_waterstate.numwaterplanes = 0;
8687 if (r_waterstate.enabled)
8688 R_RenderWaterPlanes();
8690 r_refdef.view.showdebug = true;
8692 r_waterstate.numwaterplanes = 0;
8694 R_ResetViewRendering2D();
8696 R_Bloom_CopyHDRTexture();
8697 R_Bloom_MakeTexture();
8699 // restore the view settings
8700 r_waterstate.enabled = oldwaterstate;
8701 r_refdef.view.width = oldwidth;
8702 r_refdef.view.height = oldheight;
8703 r_refdef.view.colorscale = oldcolorscale;
8705 R_ResetViewRendering3D();
8707 R_ClearScreen(r_refdef.fogenabled);
8708 if (r_timereport_active)
8709 R_TimeReport("viewclear");
8712 static void R_BlendView(void)
8714 unsigned int permutation;
8715 float uservecs[4][4];
8717 switch (vid.renderpath)
8719 case RENDERPATH_GL20:
8720 case RENDERPATH_D3D9:
8721 case RENDERPATH_D3D10:
8722 case RENDERPATH_D3D11:
8723 case RENDERPATH_SOFT:
8724 case RENDERPATH_GLES2:
8726 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
8727 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
8728 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
8729 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
8730 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
8732 if (r_bloomstate.texture_screen)
8734 // make sure the buffer is available
8735 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
8737 R_ResetViewRendering2D();
8739 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
8741 // declare variables
8743 static float avgspeed;
8745 speed = VectorLength(cl.movement_velocity);
8747 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
8748 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
8750 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
8751 speed = bound(0, speed, 1);
8752 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
8754 // calculate values into a standard alpha
8755 cl.motionbluralpha = 1 - exp(-
8757 (r_motionblur.value * speed / 80)
8759 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
8762 max(0.0001, cl.time - cl.oldtime) // fps independent
8765 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
8766 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
8768 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
8770 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8771 GL_Color(1, 1, 1, cl.motionbluralpha);
8772 switch(vid.renderpath)
8774 case RENDERPATH_GL11:
8775 case RENDERPATH_GL13:
8776 case RENDERPATH_GL20:
8777 case RENDERPATH_SOFT:
8778 case RENDERPATH_GLES2:
8779 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8781 case RENDERPATH_D3D9:
8782 case RENDERPATH_D3D10:
8783 case RENDERPATH_D3D11:
8784 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8787 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
8788 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8789 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8793 // copy view into the screen texture
8794 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);
8795 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8797 else if (!r_bloomstate.texture_bloom)
8799 // we may still have to do view tint...
8800 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
8802 // apply a color tint to the whole view
8803 R_ResetViewRendering2D();
8804 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8805 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
8806 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8807 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8808 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8810 break; // no screen processing, no bloom, skip it
8813 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
8815 // render simple bloom effect
8816 // copy the screen and shrink it and darken it for the bloom process
8817 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
8818 // make the bloom texture
8819 R_Bloom_MakeTexture();
8822 #if _MSC_VER >= 1400
8823 #define sscanf sscanf_s
8825 memset(uservecs, 0, sizeof(uservecs));
8826 if (r_glsl_postprocess_uservec1_enable.integer)
8827 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
8828 if (r_glsl_postprocess_uservec2_enable.integer)
8829 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
8830 if (r_glsl_postprocess_uservec3_enable.integer)
8831 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
8832 if (r_glsl_postprocess_uservec4_enable.integer)
8833 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
8835 R_ResetViewRendering2D();
8836 GL_Color(1, 1, 1, 1);
8837 GL_BlendFunc(GL_ONE, GL_ZERO);
8839 switch(vid.renderpath)
8841 case RENDERPATH_GL20:
8842 case RENDERPATH_GLES2:
8843 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
8844 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
8845 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_bloomstate.texture_screen);
8846 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_bloomstate.texture_bloom );
8847 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
8848 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]);
8849 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
8850 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]);
8851 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]);
8852 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]);
8853 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]);
8854 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
8855 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
8856 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);
8858 case RENDERPATH_D3D9:
8860 // 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...
8861 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
8862 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
8863 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
8864 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
8865 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
8866 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8867 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
8868 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
8869 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
8870 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
8871 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
8872 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
8873 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
8874 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
8877 case RENDERPATH_D3D10:
8878 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
8880 case RENDERPATH_D3D11:
8881 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
8883 case RENDERPATH_SOFT:
8884 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
8885 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
8886 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
8887 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
8888 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
8889 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8890 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
8891 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
8892 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
8893 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
8894 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
8895 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
8896 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
8897 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
8902 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8903 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8905 case RENDERPATH_GL13:
8906 case RENDERPATH_GL11:
8907 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
8909 // apply a color tint to the whole view
8910 R_ResetViewRendering2D();
8911 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8912 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
8913 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8914 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8915 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8921 matrix4x4_t r_waterscrollmatrix;
8923 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
8925 if (r_refdef.fog_density)
8927 r_refdef.fogcolor[0] = r_refdef.fog_red;
8928 r_refdef.fogcolor[1] = r_refdef.fog_green;
8929 r_refdef.fogcolor[2] = r_refdef.fog_blue;
8931 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
8932 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
8933 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
8934 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
8938 VectorCopy(r_refdef.fogcolor, fogvec);
8939 // color.rgb *= ContrastBoost * SceneBrightness;
8940 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
8941 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
8942 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
8943 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
8948 void R_UpdateVariables(void)
8952 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
8954 r_refdef.farclip = r_farclip_base.value;
8955 if (r_refdef.scene.worldmodel)
8956 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
8957 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
8959 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
8960 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
8961 r_refdef.polygonfactor = 0;
8962 r_refdef.polygonoffset = 0;
8963 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
8964 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
8966 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
8967 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
8968 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
8969 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
8970 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
8971 if (FAKELIGHT_ENABLED)
8973 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
8975 if (r_showsurfaces.integer)
8977 r_refdef.scene.rtworld = false;
8978 r_refdef.scene.rtworldshadows = false;
8979 r_refdef.scene.rtdlight = false;
8980 r_refdef.scene.rtdlightshadows = false;
8981 r_refdef.lightmapintensity = 0;
8984 if (gamemode == GAME_NEHAHRA)
8986 if (gl_fogenable.integer)
8988 r_refdef.oldgl_fogenable = true;
8989 r_refdef.fog_density = gl_fogdensity.value;
8990 r_refdef.fog_red = gl_fogred.value;
8991 r_refdef.fog_green = gl_foggreen.value;
8992 r_refdef.fog_blue = gl_fogblue.value;
8993 r_refdef.fog_alpha = 1;
8994 r_refdef.fog_start = 0;
8995 r_refdef.fog_end = gl_skyclip.value;
8996 r_refdef.fog_height = 1<<30;
8997 r_refdef.fog_fadedepth = 128;
8999 else if (r_refdef.oldgl_fogenable)
9001 r_refdef.oldgl_fogenable = false;
9002 r_refdef.fog_density = 0;
9003 r_refdef.fog_red = 0;
9004 r_refdef.fog_green = 0;
9005 r_refdef.fog_blue = 0;
9006 r_refdef.fog_alpha = 0;
9007 r_refdef.fog_start = 0;
9008 r_refdef.fog_end = 0;
9009 r_refdef.fog_height = 1<<30;
9010 r_refdef.fog_fadedepth = 128;
9014 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
9015 r_refdef.fog_start = max(0, r_refdef.fog_start);
9016 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
9018 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
9020 if (r_refdef.fog_density && r_drawfog.integer)
9022 r_refdef.fogenabled = true;
9023 // this is the point where the fog reaches 0.9986 alpha, which we
9024 // consider a good enough cutoff point for the texture
9025 // (0.9986 * 256 == 255.6)
9026 if (r_fog_exp2.integer)
9027 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
9029 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
9030 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
9031 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
9032 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
9033 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
9034 R_BuildFogHeightTexture();
9035 // fog color was already set
9036 // update the fog texture
9037 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)
9038 R_BuildFogTexture();
9039 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
9040 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
9043 r_refdef.fogenabled = false;
9045 switch(vid.renderpath)
9047 case RENDERPATH_GL20:
9048 case RENDERPATH_D3D9:
9049 case RENDERPATH_D3D10:
9050 case RENDERPATH_D3D11:
9051 case RENDERPATH_SOFT:
9052 case RENDERPATH_GLES2:
9053 if(v_glslgamma.integer && !vid_gammatables_trivial)
9055 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
9057 // build GLSL gamma texture
9058 #define RAMPWIDTH 256
9059 unsigned short ramp[RAMPWIDTH * 3];
9060 unsigned char rampbgr[RAMPWIDTH][4];
9063 r_texture_gammaramps_serial = vid_gammatables_serial;
9065 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
9066 for(i = 0; i < RAMPWIDTH; ++i)
9068 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9069 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9070 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
9073 if (r_texture_gammaramps)
9075 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
9079 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
9085 // remove GLSL gamma texture
9088 case RENDERPATH_GL13:
9089 case RENDERPATH_GL11:
9094 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
9095 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
9101 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
9102 if( scenetype != r_currentscenetype ) {
9103 // store the old scenetype
9104 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
9105 r_currentscenetype = scenetype;
9106 // move in the new scene
9107 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
9116 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
9118 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
9119 if( scenetype == r_currentscenetype ) {
9120 return &r_refdef.scene;
9122 return &r_scenes_store[ scenetype ];
9131 int dpsoftrast_test;
9132 void R_RenderView(void)
9134 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
9136 dpsoftrast_test = r_test.integer;
9138 if (r_timereport_active)
9139 R_TimeReport("start");
9140 r_textureframe++; // used only by R_GetCurrentTexture
9141 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9143 if(R_CompileShader_CheckStaticParms())
9146 if (!r_drawentities.integer)
9147 r_refdef.scene.numentities = 0;
9149 R_AnimCache_ClearCache();
9150 R_FrameData_NewFrame();
9152 /* adjust for stereo display */
9153 if(R_Stereo_Active())
9155 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);
9156 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
9159 if (r_refdef.view.isoverlay)
9161 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
9162 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
9163 R_TimeReport("depthclear");
9165 r_refdef.view.showdebug = false;
9167 r_waterstate.enabled = false;
9168 r_waterstate.numwaterplanes = 0;
9172 r_refdef.view.matrix = originalmatrix;
9178 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
9180 r_refdef.view.matrix = originalmatrix;
9181 return; //Host_Error ("R_RenderView: NULL worldmodel");
9184 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
9186 R_RenderView_UpdateViewVectors();
9188 R_Shadow_UpdateWorldLightSelection();
9190 R_Bloom_StartFrame();
9191 R_Water_StartFrame();
9194 if (r_timereport_active)
9195 R_TimeReport("viewsetup");
9197 R_ResetViewRendering3D();
9199 if (r_refdef.view.clear || r_refdef.fogenabled)
9201 R_ClearScreen(r_refdef.fogenabled);
9202 if (r_timereport_active)
9203 R_TimeReport("viewclear");
9205 r_refdef.view.clear = true;
9207 // this produces a bloom texture to be used in R_BlendView() later
9208 if (r_hdr.integer && r_bloomstate.bloomwidth)
9210 R_HDR_RenderBloomTexture();
9211 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
9212 r_textureframe++; // used only by R_GetCurrentTexture
9215 r_refdef.view.showdebug = true;
9218 if (r_timereport_active)
9219 R_TimeReport("visibility");
9221 r_waterstate.numwaterplanes = 0;
9222 if (r_waterstate.enabled)
9223 R_RenderWaterPlanes();
9226 r_waterstate.numwaterplanes = 0;
9229 if (r_timereport_active)
9230 R_TimeReport("blendview");
9232 GL_Scissor(0, 0, vid.width, vid.height);
9233 GL_ScissorTest(false);
9235 r_refdef.view.matrix = originalmatrix;
9240 void R_RenderWaterPlanes(void)
9242 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
9244 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
9245 if (r_timereport_active)
9246 R_TimeReport("waterworld");
9249 // don't let sound skip if going slow
9250 if (r_refdef.scene.extraupdate)
9253 R_DrawModelsAddWaterPlanes();
9254 if (r_timereport_active)
9255 R_TimeReport("watermodels");
9257 if (r_waterstate.numwaterplanes)
9259 R_Water_ProcessPlanes();
9260 if (r_timereport_active)
9261 R_TimeReport("waterscenes");
9265 extern void R_DrawLightningBeams (void);
9266 extern void VM_CL_AddPolygonsToMeshQueue (void);
9267 extern void R_DrawPortals (void);
9268 extern cvar_t cl_locs_show;
9269 static void R_DrawLocs(void);
9270 static void R_DrawEntityBBoxes(void);
9271 static void R_DrawModelDecals(void);
9272 extern void R_DrawModelShadows(void);
9273 extern void R_DrawModelShadowMaps(void);
9274 extern cvar_t cl_decals_newsystem;
9275 extern qboolean r_shadow_usingdeferredprepass;
9276 void R_RenderScene(void)
9278 qboolean shadowmapping = false;
9280 if (r_timereport_active)
9281 R_TimeReport("beginscene");
9283 r_refdef.stats.renders++;
9287 // don't let sound skip if going slow
9288 if (r_refdef.scene.extraupdate)
9291 R_MeshQueue_BeginScene();
9295 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);
9297 if (r_timereport_active)
9298 R_TimeReport("skystartframe");
9300 if (cl.csqc_vidvars.drawworld)
9302 // don't let sound skip if going slow
9303 if (r_refdef.scene.extraupdate)
9306 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
9308 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
9309 if (r_timereport_active)
9310 R_TimeReport("worldsky");
9313 if (R_DrawBrushModelsSky() && r_timereport_active)
9314 R_TimeReport("bmodelsky");
9316 if (skyrendermasked && skyrenderlater)
9318 // we have to force off the water clipping plane while rendering sky
9322 if (r_timereport_active)
9323 R_TimeReport("sky");
9327 R_AnimCache_CacheVisibleEntities();
9328 if (r_timereport_active)
9329 R_TimeReport("animation");
9331 R_Shadow_PrepareLights();
9332 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
9333 R_Shadow_PrepareModelShadows();
9334 if (r_timereport_active)
9335 R_TimeReport("preparelights");
9337 if (R_Shadow_ShadowMappingEnabled())
9338 shadowmapping = true;
9340 if (r_shadow_usingdeferredprepass)
9341 R_Shadow_DrawPrepass();
9343 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
9345 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
9346 if (r_timereport_active)
9347 R_TimeReport("worlddepth");
9349 if (r_depthfirst.integer >= 2)
9351 R_DrawModelsDepth();
9352 if (r_timereport_active)
9353 R_TimeReport("modeldepth");
9356 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
9358 R_DrawModelShadowMaps();
9359 R_ResetViewRendering3D();
9360 // don't let sound skip if going slow
9361 if (r_refdef.scene.extraupdate)
9365 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
9367 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
9368 if (r_timereport_active)
9369 R_TimeReport("world");
9372 // don't let sound skip if going slow
9373 if (r_refdef.scene.extraupdate)
9377 if (r_timereport_active)
9378 R_TimeReport("models");
9380 // don't let sound skip if going slow
9381 if (r_refdef.scene.extraupdate)
9384 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9386 R_DrawModelShadows();
9387 R_ResetViewRendering3D();
9388 // don't let sound skip if going slow
9389 if (r_refdef.scene.extraupdate)
9393 if (!r_shadow_usingdeferredprepass)
9395 R_Shadow_DrawLights();
9396 if (r_timereport_active)
9397 R_TimeReport("rtlights");
9400 // don't let sound skip if going slow
9401 if (r_refdef.scene.extraupdate)
9404 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9406 R_DrawModelShadows();
9407 R_ResetViewRendering3D();
9408 // don't let sound skip if going slow
9409 if (r_refdef.scene.extraupdate)
9413 if (cl.csqc_vidvars.drawworld)
9415 if (cl_decals_newsystem.integer)
9417 R_DrawModelDecals();
9418 if (r_timereport_active)
9419 R_TimeReport("modeldecals");
9424 if (r_timereport_active)
9425 R_TimeReport("decals");
9429 if (r_timereport_active)
9430 R_TimeReport("particles");
9433 if (r_timereport_active)
9434 R_TimeReport("explosions");
9436 R_DrawLightningBeams();
9437 if (r_timereport_active)
9438 R_TimeReport("lightning");
9441 VM_CL_AddPolygonsToMeshQueue();
9443 if (r_refdef.view.showdebug)
9445 if (cl_locs_show.integer)
9448 if (r_timereport_active)
9449 R_TimeReport("showlocs");
9452 if (r_drawportals.integer)
9455 if (r_timereport_active)
9456 R_TimeReport("portals");
9459 if (r_showbboxes.value > 0)
9461 R_DrawEntityBBoxes();
9462 if (r_timereport_active)
9463 R_TimeReport("bboxes");
9467 R_MeshQueue_RenderTransparent();
9468 if (r_timereport_active)
9469 R_TimeReport("drawtrans");
9471 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))
9473 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
9474 if (r_timereport_active)
9475 R_TimeReport("worlddebug");
9476 R_DrawModelsDebug();
9477 if (r_timereport_active)
9478 R_TimeReport("modeldebug");
9481 if (cl.csqc_vidvars.drawworld)
9483 R_Shadow_DrawCoronas();
9484 if (r_timereport_active)
9485 R_TimeReport("coronas");
9490 GL_DepthTest(false);
9491 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
9492 GL_Color(1, 1, 1, 1);
9493 qglBegin(GL_POLYGON);
9494 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
9495 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
9496 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
9497 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
9499 qglBegin(GL_POLYGON);
9500 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]);
9501 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]);
9502 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]);
9503 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]);
9505 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
9509 // don't let sound skip if going slow
9510 if (r_refdef.scene.extraupdate)
9513 R_ResetViewRendering2D();
9516 static const unsigned short bboxelements[36] =
9526 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
9529 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
9531 RSurf_ActiveWorldEntity();
9533 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9534 GL_DepthMask(false);
9535 GL_DepthRange(0, 1);
9536 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
9537 // R_Mesh_ResetTextureState();
9539 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
9540 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
9541 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
9542 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
9543 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
9544 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
9545 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
9546 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
9547 R_FillColors(color4f, 8, cr, cg, cb, ca);
9548 if (r_refdef.fogenabled)
9550 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
9552 f1 = RSurf_FogVertex(v);
9554 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
9555 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
9556 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
9559 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
9560 R_Mesh_ResetTextureState();
9561 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9562 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
9565 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9569 prvm_edict_t *edict;
9570 prvm_prog_t *prog_save = prog;
9572 // this function draws bounding boxes of server entities
9576 GL_CullFace(GL_NONE);
9577 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9581 for (i = 0;i < numsurfaces;i++)
9583 edict = PRVM_EDICT_NUM(surfacelist[i]);
9584 switch ((int)edict->fields.server->solid)
9586 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
9587 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
9588 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
9589 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
9590 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
9591 default: Vector4Set(color, 0, 0, 0, 0.50);break;
9593 color[3] *= r_showbboxes.value;
9594 color[3] = bound(0, color[3], 1);
9595 GL_DepthTest(!r_showdisabledepthtest.integer);
9596 GL_CullFace(r_refdef.view.cullface_front);
9597 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
9603 static void R_DrawEntityBBoxes(void)
9606 prvm_edict_t *edict;
9608 prvm_prog_t *prog_save = prog;
9610 // this function draws bounding boxes of server entities
9616 for (i = 0;i < prog->num_edicts;i++)
9618 edict = PRVM_EDICT_NUM(i);
9619 if (edict->priv.server->free)
9621 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
9622 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
9624 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
9626 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
9627 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
9633 static const int nomodelelement3i[24] =
9645 static const unsigned short nomodelelement3s[24] =
9657 static const float nomodelvertex3f[6*3] =
9667 static const float nomodelcolor4f[6*4] =
9669 0.0f, 0.0f, 0.5f, 1.0f,
9670 0.0f, 0.0f, 0.5f, 1.0f,
9671 0.0f, 0.5f, 0.0f, 1.0f,
9672 0.0f, 0.5f, 0.0f, 1.0f,
9673 0.5f, 0.0f, 0.0f, 1.0f,
9674 0.5f, 0.0f, 0.0f, 1.0f
9677 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9683 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);
9685 // this is only called once per entity so numsurfaces is always 1, and
9686 // surfacelist is always {0}, so this code does not handle batches
9688 if (rsurface.ent_flags & RENDER_ADDITIVE)
9690 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
9691 GL_DepthMask(false);
9693 else if (rsurface.colormod[3] < 1)
9695 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9696 GL_DepthMask(false);
9700 GL_BlendFunc(GL_ONE, GL_ZERO);
9703 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
9704 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
9705 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
9706 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
9707 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
9708 for (i = 0, c = color4f;i < 6;i++, c += 4)
9710 c[0] *= rsurface.colormod[0];
9711 c[1] *= rsurface.colormod[1];
9712 c[2] *= rsurface.colormod[2];
9713 c[3] *= rsurface.colormod[3];
9715 if (r_refdef.fogenabled)
9717 for (i = 0, c = color4f;i < 6;i++, c += 4)
9719 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
9721 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
9722 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
9723 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
9726 // R_Mesh_ResetTextureState();
9727 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9728 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
9729 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
9732 void R_DrawNoModel(entity_render_t *ent)
9735 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
9736 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
9737 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
9739 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
9742 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
9744 vec3_t right1, right2, diff, normal;
9746 VectorSubtract (org2, org1, normal);
9748 // calculate 'right' vector for start
9749 VectorSubtract (r_refdef.view.origin, org1, diff);
9750 CrossProduct (normal, diff, right1);
9751 VectorNormalize (right1);
9753 // calculate 'right' vector for end
9754 VectorSubtract (r_refdef.view.origin, org2, diff);
9755 CrossProduct (normal, diff, right2);
9756 VectorNormalize (right2);
9758 vert[ 0] = org1[0] + width * right1[0];
9759 vert[ 1] = org1[1] + width * right1[1];
9760 vert[ 2] = org1[2] + width * right1[2];
9761 vert[ 3] = org1[0] - width * right1[0];
9762 vert[ 4] = org1[1] - width * right1[1];
9763 vert[ 5] = org1[2] - width * right1[2];
9764 vert[ 6] = org2[0] - width * right2[0];
9765 vert[ 7] = org2[1] - width * right2[1];
9766 vert[ 8] = org2[2] - width * right2[2];
9767 vert[ 9] = org2[0] + width * right2[0];
9768 vert[10] = org2[1] + width * right2[1];
9769 vert[11] = org2[2] + width * right2[2];
9772 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)
9774 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
9775 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
9776 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
9777 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
9778 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
9779 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
9780 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
9781 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
9782 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
9783 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
9784 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
9785 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
9788 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
9793 VectorSet(v, x, y, z);
9794 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
9795 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
9797 if (i == mesh->numvertices)
9799 if (mesh->numvertices < mesh->maxvertices)
9801 VectorCopy(v, vertex3f);
9802 mesh->numvertices++;
9804 return mesh->numvertices;
9810 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
9814 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
9815 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
9816 e = mesh->element3i + mesh->numtriangles * 3;
9817 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
9819 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
9820 if (mesh->numtriangles < mesh->maxtriangles)
9825 mesh->numtriangles++;
9827 element[1] = element[2];
9831 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
9835 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
9836 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
9837 e = mesh->element3i + mesh->numtriangles * 3;
9838 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
9840 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
9841 if (mesh->numtriangles < mesh->maxtriangles)
9846 mesh->numtriangles++;
9848 element[1] = element[2];
9852 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
9853 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
9855 int planenum, planenum2;
9858 mplane_t *plane, *plane2;
9860 double temppoints[2][256*3];
9861 // figure out how large a bounding box we need to properly compute this brush
9863 for (w = 0;w < numplanes;w++)
9864 maxdist = max(maxdist, fabs(planes[w].dist));
9865 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
9866 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
9867 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
9871 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
9872 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
9874 if (planenum2 == planenum)
9876 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);
9879 if (tempnumpoints < 3)
9881 // generate elements forming a triangle fan for this polygon
9882 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
9886 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)
9888 texturelayer_t *layer;
9889 layer = t->currentlayers + t->currentnumlayers++;
9891 layer->depthmask = depthmask;
9892 layer->blendfunc1 = blendfunc1;
9893 layer->blendfunc2 = blendfunc2;
9894 layer->texture = texture;
9895 layer->texmatrix = *matrix;
9896 layer->color[0] = r;
9897 layer->color[1] = g;
9898 layer->color[2] = b;
9899 layer->color[3] = a;
9902 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
9904 if(parms[0] == 0 && parms[1] == 0)
9906 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
9907 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
9912 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
9915 index = parms[2] + r_refdef.scene.time * parms[3];
9916 index -= floor(index);
9917 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
9920 case Q3WAVEFUNC_NONE:
9921 case Q3WAVEFUNC_NOISE:
9922 case Q3WAVEFUNC_COUNT:
9925 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
9926 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
9927 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
9928 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
9929 case Q3WAVEFUNC_TRIANGLE:
9931 f = index - floor(index);
9942 f = parms[0] + parms[1] * f;
9943 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
9944 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
9948 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
9953 matrix4x4_t matrix, temp;
9954 switch(tcmod->tcmod)
9958 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
9959 matrix = r_waterscrollmatrix;
9961 matrix = identitymatrix;
9963 case Q3TCMOD_ENTITYTRANSLATE:
9964 // this is used in Q3 to allow the gamecode to control texcoord
9965 // scrolling on the entity, which is not supported in darkplaces yet.
9966 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
9968 case Q3TCMOD_ROTATE:
9969 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
9970 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
9971 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
9974 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
9976 case Q3TCMOD_SCROLL:
9977 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
9979 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
9980 w = (int) tcmod->parms[0];
9981 h = (int) tcmod->parms[1];
9982 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
9984 idx = (int) floor(f * w * h);
9985 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
9987 case Q3TCMOD_STRETCH:
9988 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
9989 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
9991 case Q3TCMOD_TRANSFORM:
9992 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
9993 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
9994 VectorSet(tcmat + 6, 0 , 0 , 1);
9995 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
9996 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
9998 case Q3TCMOD_TURBULENT:
9999 // this is handled in the RSurf_PrepareVertices function
10000 matrix = identitymatrix;
10004 Matrix4x4_Concat(texmatrix, &matrix, &temp);
10007 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
10009 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
10010 char name[MAX_QPATH];
10011 skinframe_t *skinframe;
10012 unsigned char pixels[296*194];
10013 strlcpy(cache->name, skinname, sizeof(cache->name));
10014 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
10015 if (developer_loading.integer)
10016 Con_Printf("loading %s\n", name);
10017 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
10018 if (!skinframe || !skinframe->base)
10021 fs_offset_t filesize;
10023 f = FS_LoadFile(name, tempmempool, true, &filesize);
10026 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
10027 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
10031 cache->skinframe = skinframe;
10034 texture_t *R_GetCurrentTexture(texture_t *t)
10037 const entity_render_t *ent = rsurface.entity;
10038 dp_model_t *model = ent->model;
10039 q3shaderinfo_layer_tcmod_t *tcmod;
10041 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
10042 return t->currentframe;
10043 t->update_lastrenderframe = r_textureframe;
10044 t->update_lastrenderentity = (void *)ent;
10046 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
10047 t->camera_entity = ent->entitynumber;
10049 t->camera_entity = 0;
10051 // switch to an alternate material if this is a q1bsp animated material
10053 texture_t *texture = t;
10054 int s = rsurface.ent_skinnum;
10055 if ((unsigned int)s >= (unsigned int)model->numskins)
10057 if (model->skinscenes)
10059 if (model->skinscenes[s].framecount > 1)
10060 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
10062 s = model->skinscenes[s].firstframe;
10065 t = t + s * model->num_surfaces;
10068 // use an alternate animation if the entity's frame is not 0,
10069 // and only if the texture has an alternate animation
10070 if (rsurface.ent_alttextures && t->anim_total[1])
10071 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
10073 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
10075 texture->currentframe = t;
10078 // update currentskinframe to be a qw skin or animation frame
10079 if (rsurface.ent_qwskin >= 0)
10081 i = rsurface.ent_qwskin;
10082 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
10084 r_qwskincache_size = cl.maxclients;
10086 Mem_Free(r_qwskincache);
10087 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
10089 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
10090 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
10091 t->currentskinframe = r_qwskincache[i].skinframe;
10092 if (t->currentskinframe == NULL)
10093 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10095 else if (t->numskinframes >= 2)
10096 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10097 if (t->backgroundnumskinframes >= 2)
10098 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
10100 t->currentmaterialflags = t->basematerialflags;
10101 t->currentalpha = rsurface.colormod[3];
10102 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
10103 t->currentalpha *= r_wateralpha.value;
10104 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
10105 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
10106 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
10107 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
10108 if (!(rsurface.ent_flags & RENDER_LIGHT))
10109 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
10110 else if (FAKELIGHT_ENABLED)
10112 // no modellight if using fakelight for the map
10114 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10116 // pick a model lighting mode
10117 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
10118 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
10120 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
10122 if (rsurface.ent_flags & RENDER_ADDITIVE)
10123 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10124 else if (t->currentalpha < 1)
10125 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10126 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
10127 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
10128 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
10129 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
10130 if (t->backgroundnumskinframes)
10131 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
10132 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
10134 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
10135 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
10138 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
10139 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
10140 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
10142 // there is no tcmod
10143 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10145 t->currenttexmatrix = r_waterscrollmatrix;
10146 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
10148 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
10150 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
10151 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
10154 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10155 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
10156 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10157 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
10159 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
10160 if (t->currentskinframe->qpixels)
10161 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
10162 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
10163 if (!t->basetexture)
10164 t->basetexture = r_texture_notexture;
10165 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
10166 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
10167 t->nmaptexture = t->currentskinframe->nmap;
10168 if (!t->nmaptexture)
10169 t->nmaptexture = r_texture_blanknormalmap;
10170 t->glosstexture = r_texture_black;
10171 t->glowtexture = t->currentskinframe->glow;
10172 t->fogtexture = t->currentskinframe->fog;
10173 t->reflectmasktexture = t->currentskinframe->reflect;
10174 if (t->backgroundnumskinframes)
10176 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
10177 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
10178 t->backgroundglosstexture = r_texture_black;
10179 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
10180 if (!t->backgroundnmaptexture)
10181 t->backgroundnmaptexture = r_texture_blanknormalmap;
10185 t->backgroundbasetexture = r_texture_white;
10186 t->backgroundnmaptexture = r_texture_blanknormalmap;
10187 t->backgroundglosstexture = r_texture_black;
10188 t->backgroundglowtexture = NULL;
10190 t->specularpower = r_shadow_glossexponent.value;
10191 // TODO: store reference values for these in the texture?
10192 t->specularscale = 0;
10193 if (r_shadow_gloss.integer > 0)
10195 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
10197 if (r_shadow_glossintensity.value > 0)
10199 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
10200 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
10201 t->specularscale = r_shadow_glossintensity.value;
10204 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
10206 t->glosstexture = r_texture_white;
10207 t->backgroundglosstexture = r_texture_white;
10208 t->specularscale = r_shadow_gloss2intensity.value;
10209 t->specularpower = r_shadow_gloss2exponent.value;
10212 t->specularscale *= t->specularscalemod;
10213 t->specularpower *= t->specularpowermod;
10215 // lightmaps mode looks bad with dlights using actual texturing, so turn
10216 // off the colormap and glossmap, but leave the normalmap on as it still
10217 // accurately represents the shading involved
10218 if (gl_lightmaps.integer)
10220 t->basetexture = r_texture_grey128;
10221 t->pantstexture = r_texture_black;
10222 t->shirttexture = r_texture_black;
10223 t->nmaptexture = r_texture_blanknormalmap;
10224 t->glosstexture = r_texture_black;
10225 t->glowtexture = NULL;
10226 t->fogtexture = NULL;
10227 t->reflectmasktexture = NULL;
10228 t->backgroundbasetexture = NULL;
10229 t->backgroundnmaptexture = r_texture_blanknormalmap;
10230 t->backgroundglosstexture = r_texture_black;
10231 t->backgroundglowtexture = NULL;
10232 t->specularscale = 0;
10233 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
10236 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
10237 VectorClear(t->dlightcolor);
10238 t->currentnumlayers = 0;
10239 if (t->currentmaterialflags & MATERIALFLAG_WALL)
10241 int blendfunc1, blendfunc2;
10242 qboolean depthmask;
10243 if (t->currentmaterialflags & MATERIALFLAG_ADD)
10245 blendfunc1 = GL_SRC_ALPHA;
10246 blendfunc2 = GL_ONE;
10248 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
10250 blendfunc1 = GL_SRC_ALPHA;
10251 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
10253 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10255 blendfunc1 = t->customblendfunc[0];
10256 blendfunc2 = t->customblendfunc[1];
10260 blendfunc1 = GL_ONE;
10261 blendfunc2 = GL_ZERO;
10263 // don't colormod evilblend textures
10264 if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
10265 VectorSet(t->lightmapcolor, 1, 1, 1);
10266 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
10267 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10269 // fullbright is not affected by r_refdef.lightmapintensity
10270 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]);
10271 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10272 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]);
10273 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10274 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]);
10278 vec3_t ambientcolor;
10280 // set the color tint used for lights affecting this surface
10281 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
10283 // q3bsp has no lightmap updates, so the lightstylevalue that
10284 // would normally be baked into the lightmap must be
10285 // applied to the color
10286 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
10287 if (model->type == mod_brushq3)
10288 colorscale *= r_refdef.scene.rtlightstylevalue[0];
10289 colorscale *= r_refdef.lightmapintensity;
10290 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
10291 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
10292 // basic lit geometry
10293 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]);
10294 // add pants/shirt if needed
10295 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10296 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]);
10297 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10298 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]);
10299 // now add ambient passes if needed
10300 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
10302 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]);
10303 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10304 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]);
10305 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10306 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]);
10309 if (t->glowtexture != NULL && !gl_lightmaps.integer)
10310 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]);
10311 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
10313 // if this is opaque use alpha blend which will darken the earlier
10316 // if this is an alpha blended material, all the earlier passes
10317 // were darkened by fog already, so we only need to add the fog
10318 // color ontop through the fog mask texture
10320 // if this is an additive blended material, all the earlier passes
10321 // were darkened by fog already, and we should not add fog color
10322 // (because the background was not darkened, there is no fog color
10323 // that was lost behind it).
10324 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]);
10328 return t->currentframe;
10331 rsurfacestate_t rsurface;
10333 void RSurf_ActiveWorldEntity(void)
10335 dp_model_t *model = r_refdef.scene.worldmodel;
10336 //if (rsurface.entity == r_refdef.scene.worldentity)
10338 rsurface.entity = r_refdef.scene.worldentity;
10339 rsurface.skeleton = NULL;
10340 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
10341 rsurface.ent_skinnum = 0;
10342 rsurface.ent_qwskin = -1;
10343 rsurface.ent_shadertime = 0;
10344 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
10345 rsurface.matrix = identitymatrix;
10346 rsurface.inversematrix = identitymatrix;
10347 rsurface.matrixscale = 1;
10348 rsurface.inversematrixscale = 1;
10349 R_EntityMatrix(&identitymatrix);
10350 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
10351 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
10352 rsurface.fograngerecip = r_refdef.fograngerecip;
10353 rsurface.fogheightfade = r_refdef.fogheightfade;
10354 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
10355 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10356 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10357 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10358 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10359 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10360 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10361 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
10362 rsurface.colormod[3] = 1;
10363 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);
10364 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10365 rsurface.frameblend[0].lerp = 1;
10366 rsurface.ent_alttextures = false;
10367 rsurface.basepolygonfactor = r_refdef.polygonfactor;
10368 rsurface.basepolygonoffset = r_refdef.polygonoffset;
10369 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
10370 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10371 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10372 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10373 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10374 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10375 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10376 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10377 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10378 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
10379 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10380 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10381 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
10382 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10383 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10384 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
10385 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10386 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10387 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
10388 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10389 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10390 rsurface.modelelement3i = model->surfmesh.data_element3i;
10391 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10392 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10393 rsurface.modelelement3s = model->surfmesh.data_element3s;
10394 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10395 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10396 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10397 rsurface.modelnumvertices = model->surfmesh.num_vertices;
10398 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10399 rsurface.modelsurfaces = model->data_surfaces;
10400 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10401 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10402 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
10403 rsurface.modelgeneratedvertex = false;
10404 rsurface.batchgeneratedvertex = false;
10405 rsurface.batchfirstvertex = 0;
10406 rsurface.batchnumvertices = 0;
10407 rsurface.batchfirsttriangle = 0;
10408 rsurface.batchnumtriangles = 0;
10409 rsurface.batchvertex3f = NULL;
10410 rsurface.batchvertex3f_vertexbuffer = NULL;
10411 rsurface.batchvertex3f_bufferoffset = 0;
10412 rsurface.batchsvector3f = NULL;
10413 rsurface.batchsvector3f_vertexbuffer = NULL;
10414 rsurface.batchsvector3f_bufferoffset = 0;
10415 rsurface.batchtvector3f = NULL;
10416 rsurface.batchtvector3f_vertexbuffer = NULL;
10417 rsurface.batchtvector3f_bufferoffset = 0;
10418 rsurface.batchnormal3f = NULL;
10419 rsurface.batchnormal3f_vertexbuffer = NULL;
10420 rsurface.batchnormal3f_bufferoffset = 0;
10421 rsurface.batchlightmapcolor4f = NULL;
10422 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10423 rsurface.batchlightmapcolor4f_bufferoffset = 0;
10424 rsurface.batchtexcoordtexture2f = NULL;
10425 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10426 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10427 rsurface.batchtexcoordlightmap2f = NULL;
10428 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10429 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10430 rsurface.batchvertexmesh = NULL;
10431 rsurface.batchvertexmeshbuffer = NULL;
10432 rsurface.batchvertex3fbuffer = NULL;
10433 rsurface.batchelement3i = NULL;
10434 rsurface.batchelement3i_indexbuffer = NULL;
10435 rsurface.batchelement3i_bufferoffset = 0;
10436 rsurface.batchelement3s = NULL;
10437 rsurface.batchelement3s_indexbuffer = NULL;
10438 rsurface.batchelement3s_bufferoffset = 0;
10439 rsurface.passcolor4f = NULL;
10440 rsurface.passcolor4f_vertexbuffer = NULL;
10441 rsurface.passcolor4f_bufferoffset = 0;
10444 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
10446 dp_model_t *model = ent->model;
10447 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
10449 rsurface.entity = (entity_render_t *)ent;
10450 rsurface.skeleton = ent->skeleton;
10451 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
10452 rsurface.ent_skinnum = ent->skinnum;
10453 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;
10454 rsurface.ent_shadertime = ent->shadertime;
10455 rsurface.ent_flags = ent->flags;
10456 rsurface.matrix = ent->matrix;
10457 rsurface.inversematrix = ent->inversematrix;
10458 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10459 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10460 R_EntityMatrix(&rsurface.matrix);
10461 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10462 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10463 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10464 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10465 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10466 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10467 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
10468 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
10469 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
10470 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
10471 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
10472 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
10473 rsurface.colormod[3] = ent->alpha;
10474 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
10475 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
10476 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
10477 rsurface.basepolygonfactor = r_refdef.polygonfactor;
10478 rsurface.basepolygonoffset = r_refdef.polygonoffset;
10479 if (ent->model->brush.submodel && !prepass)
10481 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
10482 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
10484 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
10486 if (ent->animcache_vertex3f)
10488 rsurface.modelvertex3f = ent->animcache_vertex3f;
10489 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
10490 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
10491 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
10492 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
10493 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
10494 rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
10496 else if (wanttangents)
10498 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10499 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10500 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10501 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10502 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
10503 rsurface.modelvertexmesh = NULL;
10504 rsurface.modelvertexmeshbuffer = NULL;
10505 rsurface.modelvertex3fbuffer = NULL;
10507 else if (wantnormals)
10509 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10510 rsurface.modelsvector3f = NULL;
10511 rsurface.modeltvector3f = NULL;
10512 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10513 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
10514 rsurface.modelvertexmesh = NULL;
10515 rsurface.modelvertexmeshbuffer = NULL;
10516 rsurface.modelvertex3fbuffer = NULL;
10520 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10521 rsurface.modelsvector3f = NULL;
10522 rsurface.modeltvector3f = NULL;
10523 rsurface.modelnormal3f = NULL;
10524 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
10525 rsurface.modelvertexmesh = NULL;
10526 rsurface.modelvertexmeshbuffer = NULL;
10527 rsurface.modelvertex3fbuffer = NULL;
10529 rsurface.modelvertex3f_vertexbuffer = 0;
10530 rsurface.modelvertex3f_bufferoffset = 0;
10531 rsurface.modelsvector3f_vertexbuffer = 0;
10532 rsurface.modelsvector3f_bufferoffset = 0;
10533 rsurface.modeltvector3f_vertexbuffer = 0;
10534 rsurface.modeltvector3f_bufferoffset = 0;
10535 rsurface.modelnormal3f_vertexbuffer = 0;
10536 rsurface.modelnormal3f_bufferoffset = 0;
10537 rsurface.modelgeneratedvertex = true;
10541 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
10542 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10543 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10544 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10545 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10546 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10547 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10548 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10549 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10550 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
10551 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10552 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10553 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10554 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10555 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
10556 rsurface.modelgeneratedvertex = false;
10558 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
10559 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10560 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10561 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
10562 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10563 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10564 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
10565 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10566 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10567 rsurface.modelelement3i = model->surfmesh.data_element3i;
10568 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10569 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10570 rsurface.modelelement3s = model->surfmesh.data_element3s;
10571 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10572 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10573 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10574 rsurface.modelnumvertices = model->surfmesh.num_vertices;
10575 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10576 rsurface.modelsurfaces = model->data_surfaces;
10577 rsurface.batchgeneratedvertex = false;
10578 rsurface.batchfirstvertex = 0;
10579 rsurface.batchnumvertices = 0;
10580 rsurface.batchfirsttriangle = 0;
10581 rsurface.batchnumtriangles = 0;
10582 rsurface.batchvertex3f = NULL;
10583 rsurface.batchvertex3f_vertexbuffer = NULL;
10584 rsurface.batchvertex3f_bufferoffset = 0;
10585 rsurface.batchsvector3f = NULL;
10586 rsurface.batchsvector3f_vertexbuffer = NULL;
10587 rsurface.batchsvector3f_bufferoffset = 0;
10588 rsurface.batchtvector3f = NULL;
10589 rsurface.batchtvector3f_vertexbuffer = NULL;
10590 rsurface.batchtvector3f_bufferoffset = 0;
10591 rsurface.batchnormal3f = NULL;
10592 rsurface.batchnormal3f_vertexbuffer = NULL;
10593 rsurface.batchnormal3f_bufferoffset = 0;
10594 rsurface.batchlightmapcolor4f = NULL;
10595 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10596 rsurface.batchlightmapcolor4f_bufferoffset = 0;
10597 rsurface.batchtexcoordtexture2f = NULL;
10598 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10599 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10600 rsurface.batchtexcoordlightmap2f = NULL;
10601 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10602 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10603 rsurface.batchvertexmesh = NULL;
10604 rsurface.batchvertexmeshbuffer = NULL;
10605 rsurface.batchvertex3fbuffer = NULL;
10606 rsurface.batchelement3i = NULL;
10607 rsurface.batchelement3i_indexbuffer = NULL;
10608 rsurface.batchelement3i_bufferoffset = 0;
10609 rsurface.batchelement3s = NULL;
10610 rsurface.batchelement3s_indexbuffer = NULL;
10611 rsurface.batchelement3s_bufferoffset = 0;
10612 rsurface.passcolor4f = NULL;
10613 rsurface.passcolor4f_vertexbuffer = NULL;
10614 rsurface.passcolor4f_bufferoffset = 0;
10617 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)
10619 rsurface.entity = r_refdef.scene.worldentity;
10620 rsurface.skeleton = NULL;
10621 rsurface.ent_skinnum = 0;
10622 rsurface.ent_qwskin = -1;
10623 rsurface.ent_shadertime = shadertime;
10624 rsurface.ent_flags = entflags;
10625 rsurface.modelnumvertices = numvertices;
10626 rsurface.modelnumtriangles = numtriangles;
10627 rsurface.matrix = *matrix;
10628 rsurface.inversematrix = *inversematrix;
10629 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10630 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10631 R_EntityMatrix(&rsurface.matrix);
10632 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10633 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10634 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10635 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10636 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10637 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10638 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10639 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10640 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10641 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10642 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10643 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
10644 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);
10645 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10646 rsurface.frameblend[0].lerp = 1;
10647 rsurface.ent_alttextures = false;
10648 rsurface.basepolygonfactor = r_refdef.polygonfactor;
10649 rsurface.basepolygonoffset = r_refdef.polygonoffset;
10652 rsurface.modelvertex3f = (float *)vertex3f;
10653 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10654 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10655 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10657 else if (wantnormals)
10659 rsurface.modelvertex3f = (float *)vertex3f;
10660 rsurface.modelsvector3f = NULL;
10661 rsurface.modeltvector3f = NULL;
10662 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10666 rsurface.modelvertex3f = (float *)vertex3f;
10667 rsurface.modelsvector3f = NULL;
10668 rsurface.modeltvector3f = NULL;
10669 rsurface.modelnormal3f = NULL;
10671 rsurface.modelvertexmesh = NULL;
10672 rsurface.modelvertexmeshbuffer = NULL;
10673 rsurface.modelvertex3fbuffer = NULL;
10674 rsurface.modelvertex3f_vertexbuffer = 0;
10675 rsurface.modelvertex3f_bufferoffset = 0;
10676 rsurface.modelsvector3f_vertexbuffer = 0;
10677 rsurface.modelsvector3f_bufferoffset = 0;
10678 rsurface.modeltvector3f_vertexbuffer = 0;
10679 rsurface.modeltvector3f_bufferoffset = 0;
10680 rsurface.modelnormal3f_vertexbuffer = 0;
10681 rsurface.modelnormal3f_bufferoffset = 0;
10682 rsurface.modelgeneratedvertex = true;
10683 rsurface.modellightmapcolor4f = (float *)color4f;
10684 rsurface.modellightmapcolor4f_vertexbuffer = 0;
10685 rsurface.modellightmapcolor4f_bufferoffset = 0;
10686 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
10687 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
10688 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
10689 rsurface.modeltexcoordlightmap2f = NULL;
10690 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
10691 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
10692 rsurface.modelelement3i = (int *)element3i;
10693 rsurface.modelelement3i_indexbuffer = NULL;
10694 rsurface.modelelement3i_bufferoffset = 0;
10695 rsurface.modelelement3s = (unsigned short *)element3s;
10696 rsurface.modelelement3s_indexbuffer = NULL;
10697 rsurface.modelelement3s_bufferoffset = 0;
10698 rsurface.modellightmapoffsets = NULL;
10699 rsurface.modelsurfaces = NULL;
10700 rsurface.batchgeneratedvertex = false;
10701 rsurface.batchfirstvertex = 0;
10702 rsurface.batchnumvertices = 0;
10703 rsurface.batchfirsttriangle = 0;
10704 rsurface.batchnumtriangles = 0;
10705 rsurface.batchvertex3f = NULL;
10706 rsurface.batchvertex3f_vertexbuffer = NULL;
10707 rsurface.batchvertex3f_bufferoffset = 0;
10708 rsurface.batchsvector3f = NULL;
10709 rsurface.batchsvector3f_vertexbuffer = NULL;
10710 rsurface.batchsvector3f_bufferoffset = 0;
10711 rsurface.batchtvector3f = NULL;
10712 rsurface.batchtvector3f_vertexbuffer = NULL;
10713 rsurface.batchtvector3f_bufferoffset = 0;
10714 rsurface.batchnormal3f = NULL;
10715 rsurface.batchnormal3f_vertexbuffer = NULL;
10716 rsurface.batchnormal3f_bufferoffset = 0;
10717 rsurface.batchlightmapcolor4f = NULL;
10718 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10719 rsurface.batchlightmapcolor4f_bufferoffset = 0;
10720 rsurface.batchtexcoordtexture2f = NULL;
10721 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10722 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10723 rsurface.batchtexcoordlightmap2f = NULL;
10724 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10725 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10726 rsurface.batchvertexmesh = NULL;
10727 rsurface.batchvertexmeshbuffer = NULL;
10728 rsurface.batchvertex3fbuffer = NULL;
10729 rsurface.batchelement3i = NULL;
10730 rsurface.batchelement3i_indexbuffer = NULL;
10731 rsurface.batchelement3i_bufferoffset = 0;
10732 rsurface.batchelement3s = NULL;
10733 rsurface.batchelement3s_indexbuffer = NULL;
10734 rsurface.batchelement3s_bufferoffset = 0;
10735 rsurface.passcolor4f = NULL;
10736 rsurface.passcolor4f_vertexbuffer = NULL;
10737 rsurface.passcolor4f_bufferoffset = 0;
10739 if (rsurface.modelnumvertices && rsurface.modelelement3i)
10741 if ((wantnormals || wanttangents) && !normal3f)
10743 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10744 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
10746 if (wanttangents && !svector3f)
10748 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10749 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10750 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
10755 float RSurf_FogPoint(const float *v)
10757 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
10758 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
10759 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
10760 float FogHeightFade = r_refdef.fogheightfade;
10762 unsigned int fogmasktableindex;
10763 if (r_refdef.fogplaneviewabove)
10764 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
10766 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
10767 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
10768 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
10771 float RSurf_FogVertex(const float *v)
10773 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
10774 float FogPlaneViewDist = rsurface.fogplaneviewdist;
10775 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
10776 float FogHeightFade = rsurface.fogheightfade;
10778 unsigned int fogmasktableindex;
10779 if (r_refdef.fogplaneviewabove)
10780 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
10782 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
10783 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
10784 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
10787 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
10790 for (i = 0;i < numelements;i++)
10791 outelement3i[i] = inelement3i[i] + adjust;
10794 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
10795 extern cvar_t gl_vbo;
10796 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
10804 int surfacefirsttriangle;
10805 int surfacenumtriangles;
10806 int surfacefirstvertex;
10807 int surfaceendvertex;
10808 int surfacenumvertices;
10809 int batchnumvertices;
10810 int batchnumtriangles;
10814 qboolean dynamicvertex;
10818 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
10819 float waveparms[4];
10820 q3shaderinfo_deform_t *deform;
10821 const msurface_t *surface, *firstsurface;
10822 r_vertexmesh_t *vertexmesh;
10823 if (!texturenumsurfaces)
10825 // find vertex range of this surface batch
10827 firstsurface = texturesurfacelist[0];
10828 firsttriangle = firstsurface->num_firsttriangle;
10829 batchnumvertices = 0;
10830 batchnumtriangles = 0;
10831 firstvertex = endvertex = firstsurface->num_firstvertex;
10832 for (i = 0;i < texturenumsurfaces;i++)
10834 surface = texturesurfacelist[i];
10835 if (surface != firstsurface + i)
10837 surfacefirstvertex = surface->num_firstvertex;
10838 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
10839 surfacenumvertices = surface->num_vertices;
10840 surfacenumtriangles = surface->num_triangles;
10841 if (firstvertex > surfacefirstvertex)
10842 firstvertex = surfacefirstvertex;
10843 if (endvertex < surfaceendvertex)
10844 endvertex = surfaceendvertex;
10845 batchnumvertices += surfacenumvertices;
10846 batchnumtriangles += surfacenumtriangles;
10849 // we now know the vertex range used, and if there are any gaps in it
10850 rsurface.batchfirstvertex = firstvertex;
10851 rsurface.batchnumvertices = endvertex - firstvertex;
10852 rsurface.batchfirsttriangle = firsttriangle;
10853 rsurface.batchnumtriangles = batchnumtriangles;
10855 // this variable holds flags for which properties have been updated that
10856 // may require regenerating vertexmesh array...
10859 // check if any dynamic vertex processing must occur
10860 dynamicvertex = false;
10862 // if there is a chance of animated vertex colors, it's a dynamic batch
10863 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
10865 dynamicvertex = true;
10866 batchneed |= BATCHNEED_NOGAPS;
10867 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
10870 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
10872 switch (deform->deform)
10875 case Q3DEFORM_PROJECTIONSHADOW:
10876 case Q3DEFORM_TEXT0:
10877 case Q3DEFORM_TEXT1:
10878 case Q3DEFORM_TEXT2:
10879 case Q3DEFORM_TEXT3:
10880 case Q3DEFORM_TEXT4:
10881 case Q3DEFORM_TEXT5:
10882 case Q3DEFORM_TEXT6:
10883 case Q3DEFORM_TEXT7:
10884 case Q3DEFORM_NONE:
10886 case Q3DEFORM_AUTOSPRITE:
10887 dynamicvertex = true;
10888 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10889 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10891 case Q3DEFORM_AUTOSPRITE2:
10892 dynamicvertex = true;
10893 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10894 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10896 case Q3DEFORM_NORMAL:
10897 dynamicvertex = true;
10898 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10899 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10901 case Q3DEFORM_WAVE:
10902 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10903 break; // if wavefunc is a nop, ignore this transform
10904 dynamicvertex = true;
10905 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10906 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10908 case Q3DEFORM_BULGE:
10909 dynamicvertex = true;
10910 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10911 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10913 case Q3DEFORM_MOVE:
10914 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10915 break; // if wavefunc is a nop, ignore this transform
10916 dynamicvertex = true;
10917 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
10918 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
10922 switch(rsurface.texture->tcgen.tcgen)
10925 case Q3TCGEN_TEXTURE:
10927 case Q3TCGEN_LIGHTMAP:
10928 dynamicvertex = true;
10929 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
10930 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
10932 case Q3TCGEN_VECTOR:
10933 dynamicvertex = true;
10934 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
10935 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
10937 case Q3TCGEN_ENVIRONMENT:
10938 dynamicvertex = true;
10939 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
10940 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
10943 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10945 dynamicvertex = true;
10946 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10947 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
10950 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
10952 dynamicvertex = true;
10953 batchneed |= BATCHNEED_NOGAPS;
10954 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
10957 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
10959 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
10960 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
10961 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
10962 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
10963 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
10964 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
10965 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
10968 // when the model data has no vertex buffer (dynamic mesh), we need to
10970 if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
10971 batchneed |= BATCHNEED_NOGAPS;
10973 // if needsupdate, we have to do a dynamic vertex batch for sure
10974 if (needsupdate & batchneed)
10975 dynamicvertex = true;
10977 // see if we need to build vertexmesh from arrays
10978 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
10979 dynamicvertex = true;
10981 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
10982 // also some drivers strongly dislike firstvertex
10983 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
10984 dynamicvertex = true;
10986 rsurface.batchvertex3f = rsurface.modelvertex3f;
10987 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
10988 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
10989 rsurface.batchsvector3f = rsurface.modelsvector3f;
10990 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
10991 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
10992 rsurface.batchtvector3f = rsurface.modeltvector3f;
10993 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
10994 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
10995 rsurface.batchnormal3f = rsurface.modelnormal3f;
10996 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
10997 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
10998 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
10999 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
11000 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
11001 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
11002 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
11003 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
11004 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
11005 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
11006 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
11007 rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
11008 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
11009 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
11010 rsurface.batchelement3i = rsurface.modelelement3i;
11011 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
11012 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
11013 rsurface.batchelement3s = rsurface.modelelement3s;
11014 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
11015 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
11017 // if any dynamic vertex processing has to occur in software, we copy the
11018 // entire surface list together before processing to rebase the vertices
11019 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
11021 // if any gaps exist and we do not have a static vertex buffer, we have to
11022 // copy the surface list together to avoid wasting upload bandwidth on the
11023 // vertices in the gaps.
11025 // if gaps exist and we have a static vertex buffer, we still have to
11026 // combine the index buffer ranges into one dynamic index buffer.
11028 // in all cases we end up with data that can be drawn in one call.
11030 if (!dynamicvertex)
11032 // static vertex data, just set pointers...
11033 rsurface.batchgeneratedvertex = false;
11034 // if there are gaps, we want to build a combined index buffer,
11035 // otherwise use the original static buffer with an appropriate offset
11038 // build a new triangle elements array for this batch
11039 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
11040 rsurface.batchfirsttriangle = 0;
11042 for (i = 0;i < texturenumsurfaces;i++)
11044 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11045 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11046 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
11047 numtriangles += surfacenumtriangles;
11049 rsurface.batchelement3i_indexbuffer = NULL;
11050 rsurface.batchelement3i_bufferoffset = 0;
11051 rsurface.batchelement3s = NULL;
11052 rsurface.batchelement3s_indexbuffer = NULL;
11053 rsurface.batchelement3s_bufferoffset = 0;
11054 if (endvertex <= 65536)
11056 // make a 16bit (unsigned short) index array if possible
11057 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
11058 for (i = 0;i < numtriangles*3;i++)
11059 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
11065 // something needs software processing, do it for real...
11066 // we only directly handle separate array data in this case and then
11067 // generate interleaved data if needed...
11068 rsurface.batchgeneratedvertex = true;
11070 // now copy the vertex data into a combined array and make an index array
11071 // (this is what Quake3 does all the time)
11072 //if (gaps || rsurface.batchfirstvertex)
11074 rsurface.batchvertex3fbuffer = NULL;
11075 rsurface.batchvertexmesh = NULL;
11076 rsurface.batchvertexmeshbuffer = NULL;
11077 rsurface.batchvertex3f = NULL;
11078 rsurface.batchvertex3f_vertexbuffer = NULL;
11079 rsurface.batchvertex3f_bufferoffset = 0;
11080 rsurface.batchsvector3f = NULL;
11081 rsurface.batchsvector3f_vertexbuffer = NULL;
11082 rsurface.batchsvector3f_bufferoffset = 0;
11083 rsurface.batchtvector3f = NULL;
11084 rsurface.batchtvector3f_vertexbuffer = NULL;
11085 rsurface.batchtvector3f_bufferoffset = 0;
11086 rsurface.batchnormal3f = NULL;
11087 rsurface.batchnormal3f_vertexbuffer = NULL;
11088 rsurface.batchnormal3f_bufferoffset = 0;
11089 rsurface.batchlightmapcolor4f = NULL;
11090 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11091 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11092 rsurface.batchtexcoordtexture2f = NULL;
11093 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11094 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11095 rsurface.batchtexcoordlightmap2f = NULL;
11096 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11097 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11098 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
11099 rsurface.batchelement3i_indexbuffer = NULL;
11100 rsurface.batchelement3i_bufferoffset = 0;
11101 rsurface.batchelement3s = NULL;
11102 rsurface.batchelement3s_indexbuffer = NULL;
11103 rsurface.batchelement3s_bufferoffset = 0;
11104 // we'll only be setting up certain arrays as needed
11105 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11106 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
11107 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11108 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11109 if (batchneed & BATCHNEED_ARRAY_NORMAL)
11110 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11111 if (batchneed & BATCHNEED_ARRAY_VECTOR)
11113 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11114 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11116 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
11117 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
11118 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
11119 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11120 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
11121 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11124 for (i = 0;i < texturenumsurfaces;i++)
11126 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
11127 surfacenumvertices = texturesurfacelist[i]->num_vertices;
11128 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11129 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11130 // copy only the data requested
11131 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
11132 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
11133 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
11135 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11136 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11137 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
11138 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11139 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
11141 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11142 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11144 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
11145 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
11146 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
11147 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11148 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
11149 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11151 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
11152 numvertices += surfacenumvertices;
11153 numtriangles += surfacenumtriangles;
11156 // generate a 16bit index array as well if possible
11157 // (in general, dynamic batches fit)
11158 if (numvertices <= 65536)
11160 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
11161 for (i = 0;i < numtriangles*3;i++)
11162 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
11165 // since we've copied everything, the batch now starts at 0
11166 rsurface.batchfirstvertex = 0;
11167 rsurface.batchnumvertices = batchnumvertices;
11168 rsurface.batchfirsttriangle = 0;
11169 rsurface.batchnumtriangles = batchnumtriangles;
11172 // q1bsp surfaces rendered in vertex color mode have to have colors
11173 // calculated based on lightstyles
11174 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11176 // generate color arrays for the surfaces in this list
11180 const int *offsets;
11181 const unsigned char *lm;
11182 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
11183 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11184 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11186 for (i = 0;i < texturenumsurfaces;i++)
11188 surface = texturesurfacelist[i];
11189 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
11190 surfacenumvertices = surface->num_vertices;
11191 if (surface->lightmapinfo->samples)
11193 for (j = 0;j < surfacenumvertices;j++)
11195 lm = surface->lightmapinfo->samples + offsets[j];
11196 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
11197 VectorScale(lm, scale, c);
11198 if (surface->lightmapinfo->styles[1] != 255)
11200 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
11202 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
11203 VectorMA(c, scale, lm, c);
11204 if (surface->lightmapinfo->styles[2] != 255)
11207 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
11208 VectorMA(c, scale, lm, c);
11209 if (surface->lightmapinfo->styles[3] != 255)
11212 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
11213 VectorMA(c, scale, lm, c);
11220 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);
11226 for (j = 0;j < surfacenumvertices;j++)
11228 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
11235 // if vertices are deformed (sprite flares and things in maps, possibly
11236 // water waves, bulges and other deformations), modify the copied vertices
11238 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11240 switch (deform->deform)
11243 case Q3DEFORM_PROJECTIONSHADOW:
11244 case Q3DEFORM_TEXT0:
11245 case Q3DEFORM_TEXT1:
11246 case Q3DEFORM_TEXT2:
11247 case Q3DEFORM_TEXT3:
11248 case Q3DEFORM_TEXT4:
11249 case Q3DEFORM_TEXT5:
11250 case Q3DEFORM_TEXT6:
11251 case Q3DEFORM_TEXT7:
11252 case Q3DEFORM_NONE:
11254 case Q3DEFORM_AUTOSPRITE:
11255 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11256 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11257 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11258 VectorNormalize(newforward);
11259 VectorNormalize(newright);
11260 VectorNormalize(newup);
11261 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11262 // rsurface.batchvertex3f_vertexbuffer = NULL;
11263 // rsurface.batchvertex3f_bufferoffset = 0;
11264 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
11265 // rsurface.batchsvector3f_vertexbuffer = NULL;
11266 // rsurface.batchsvector3f_bufferoffset = 0;
11267 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
11268 // rsurface.batchtvector3f_vertexbuffer = NULL;
11269 // rsurface.batchtvector3f_bufferoffset = 0;
11270 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
11271 // rsurface.batchnormal3f_vertexbuffer = NULL;
11272 // rsurface.batchnormal3f_bufferoffset = 0;
11273 // a single autosprite surface can contain multiple sprites...
11274 for (j = 0;j < batchnumvertices - 3;j += 4)
11276 VectorClear(center);
11277 for (i = 0;i < 4;i++)
11278 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11279 VectorScale(center, 0.25f, center);
11280 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
11281 VectorCopy(rsurface.batchsvector3f + 3*j, right);
11282 VectorCopy(rsurface.batchtvector3f + 3*j, up);
11283 for (i = 0;i < 4;i++)
11285 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
11286 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
11289 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
11290 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11291 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);
11293 case Q3DEFORM_AUTOSPRITE2:
11294 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11295 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11296 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11297 VectorNormalize(newforward);
11298 VectorNormalize(newright);
11299 VectorNormalize(newup);
11300 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11301 // rsurface.batchvertex3f_vertexbuffer = NULL;
11302 // rsurface.batchvertex3f_bufferoffset = 0;
11304 const float *v1, *v2;
11314 memset(shortest, 0, sizeof(shortest));
11315 // a single autosprite surface can contain multiple sprites...
11316 for (j = 0;j < batchnumvertices - 3;j += 4)
11318 VectorClear(center);
11319 for (i = 0;i < 4;i++)
11320 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11321 VectorScale(center, 0.25f, center);
11322 // find the two shortest edges, then use them to define the
11323 // axis vectors for rotating around the central axis
11324 for (i = 0;i < 6;i++)
11326 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
11327 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
11328 l = VectorDistance2(v1, v2);
11329 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
11330 if (v1[2] != v2[2])
11331 l += (1.0f / 1024.0f);
11332 if (shortest[0].length2 > l || i == 0)
11334 shortest[1] = shortest[0];
11335 shortest[0].length2 = l;
11336 shortest[0].v1 = v1;
11337 shortest[0].v2 = v2;
11339 else if (shortest[1].length2 > l || i == 1)
11341 shortest[1].length2 = l;
11342 shortest[1].v1 = v1;
11343 shortest[1].v2 = v2;
11346 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
11347 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
11348 // this calculates the right vector from the shortest edge
11349 // and the up vector from the edge midpoints
11350 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
11351 VectorNormalize(right);
11352 VectorSubtract(end, start, up);
11353 VectorNormalize(up);
11354 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
11355 VectorSubtract(rsurface.localvieworigin, center, forward);
11356 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
11357 VectorNegate(forward, forward);
11358 VectorReflect(forward, 0, up, forward);
11359 VectorNormalize(forward);
11360 CrossProduct(up, forward, newright);
11361 VectorNormalize(newright);
11362 // rotate the quad around the up axis vector, this is made
11363 // especially easy by the fact we know the quad is flat,
11364 // so we only have to subtract the center position and
11365 // measure distance along the right vector, and then
11366 // multiply that by the newright vector and add back the
11368 // we also need to subtract the old position to undo the
11369 // displacement from the center, which we do with a
11370 // DotProduct, the subtraction/addition of center is also
11371 // optimized into DotProducts here
11372 l = DotProduct(right, center);
11373 for (i = 0;i < 4;i++)
11375 v1 = rsurface.batchvertex3f + 3*(j+i);
11376 f = DotProduct(right, v1) - l;
11377 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
11381 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
11383 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11384 // rsurface.batchnormal3f_vertexbuffer = NULL;
11385 // rsurface.batchnormal3f_bufferoffset = 0;
11386 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11388 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11390 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11391 // rsurface.batchsvector3f_vertexbuffer = NULL;
11392 // rsurface.batchsvector3f_bufferoffset = 0;
11393 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11394 // rsurface.batchtvector3f_vertexbuffer = NULL;
11395 // rsurface.batchtvector3f_bufferoffset = 0;
11396 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);
11399 case Q3DEFORM_NORMAL:
11400 // deform the normals to make reflections wavey
11401 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
11402 rsurface.batchnormal3f_vertexbuffer = NULL;
11403 rsurface.batchnormal3f_bufferoffset = 0;
11404 for (j = 0;j < batchnumvertices;j++)
11407 float *normal = rsurface.batchnormal3f + 3*j;
11408 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
11409 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
11410 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]);
11411 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]);
11412 VectorNormalize(normal);
11414 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11416 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11417 // rsurface.batchsvector3f_vertexbuffer = NULL;
11418 // rsurface.batchsvector3f_bufferoffset = 0;
11419 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11420 // rsurface.batchtvector3f_vertexbuffer = NULL;
11421 // rsurface.batchtvector3f_bufferoffset = 0;
11422 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);
11425 case Q3DEFORM_WAVE:
11426 // deform vertex array to make wavey water and flags and such
11427 waveparms[0] = deform->waveparms[0];
11428 waveparms[1] = deform->waveparms[1];
11429 waveparms[2] = deform->waveparms[2];
11430 waveparms[3] = deform->waveparms[3];
11431 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
11432 break; // if wavefunc is a nop, don't make a dynamic vertex array
11433 // this is how a divisor of vertex influence on deformation
11434 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
11435 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11436 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11437 // rsurface.batchvertex3f_vertexbuffer = NULL;
11438 // rsurface.batchvertex3f_bufferoffset = 0;
11439 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
11440 // rsurface.batchnormal3f_vertexbuffer = NULL;
11441 // rsurface.batchnormal3f_bufferoffset = 0;
11442 for (j = 0;j < batchnumvertices;j++)
11444 // if the wavefunc depends on time, evaluate it per-vertex
11447 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
11448 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11450 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
11452 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
11453 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11454 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11456 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11457 // rsurface.batchsvector3f_vertexbuffer = NULL;
11458 // rsurface.batchsvector3f_bufferoffset = 0;
11459 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11460 // rsurface.batchtvector3f_vertexbuffer = NULL;
11461 // rsurface.batchtvector3f_bufferoffset = 0;
11462 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);
11465 case Q3DEFORM_BULGE:
11466 // deform vertex array to make the surface have moving bulges
11467 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11468 // rsurface.batchvertex3f_vertexbuffer = NULL;
11469 // rsurface.batchvertex3f_bufferoffset = 0;
11470 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
11471 // rsurface.batchnormal3f_vertexbuffer = NULL;
11472 // rsurface.batchnormal3f_bufferoffset = 0;
11473 for (j = 0;j < batchnumvertices;j++)
11475 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
11476 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
11478 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
11479 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11480 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11482 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11483 // rsurface.batchsvector3f_vertexbuffer = NULL;
11484 // rsurface.batchsvector3f_bufferoffset = 0;
11485 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11486 // rsurface.batchtvector3f_vertexbuffer = NULL;
11487 // rsurface.batchtvector3f_bufferoffset = 0;
11488 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);
11491 case Q3DEFORM_MOVE:
11492 // deform vertex array
11493 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11494 break; // if wavefunc is a nop, don't make a dynamic vertex array
11495 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
11496 VectorScale(deform->parms, scale, waveparms);
11497 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11498 // rsurface.batchvertex3f_vertexbuffer = NULL;
11499 // rsurface.batchvertex3f_bufferoffset = 0;
11500 for (j = 0;j < batchnumvertices;j++)
11501 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
11506 // generate texcoords based on the chosen texcoord source
11507 switch(rsurface.texture->tcgen.tcgen)
11510 case Q3TCGEN_TEXTURE:
11512 case Q3TCGEN_LIGHTMAP:
11513 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11514 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11515 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11516 if (rsurface.batchtexcoordlightmap2f)
11517 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
11519 case Q3TCGEN_VECTOR:
11520 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11521 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11522 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11523 for (j = 0;j < batchnumvertices;j++)
11525 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
11526 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
11529 case Q3TCGEN_ENVIRONMENT:
11530 // make environment reflections using a spheremap
11531 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11532 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11533 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11534 for (j = 0;j < batchnumvertices;j++)
11536 // identical to Q3A's method, but executed in worldspace so
11537 // carried models can be shiny too
11539 float viewer[3], d, reflected[3], worldreflected[3];
11541 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
11542 // VectorNormalize(viewer);
11544 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
11546 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
11547 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
11548 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
11549 // note: this is proportinal to viewer, so we can normalize later
11551 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
11552 VectorNormalize(worldreflected);
11554 // note: this sphere map only uses world x and z!
11555 // so positive and negative y will LOOK THE SAME.
11556 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
11557 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
11561 // the only tcmod that needs software vertex processing is turbulent, so
11562 // check for it here and apply the changes if needed
11563 // and we only support that as the first one
11564 // (handling a mixture of turbulent and other tcmods would be problematic
11565 // without punting it entirely to a software path)
11566 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11568 amplitude = rsurface.texture->tcmods[0].parms[1];
11569 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
11570 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11571 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11572 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11573 for (j = 0;j < batchnumvertices;j++)
11575 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);
11576 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
11580 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11582 // convert the modified arrays to vertex structs
11583 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
11584 // rsurface.batchvertexmeshbuffer = NULL;
11585 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
11586 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11587 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
11588 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
11589 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11590 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
11591 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
11593 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11595 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
11596 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
11599 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
11600 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11601 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
11602 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
11603 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11604 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
11605 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
11606 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11607 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
11611 void RSurf_DrawBatch(void)
11613 // sometimes a zero triangle surface (usually a degenerate patch) makes it
11614 // through the pipeline, killing it earlier in the pipeline would have
11615 // per-surface overhead rather than per-batch overhead, so it's best to
11616 // reject it here, before it hits glDraw.
11617 if (rsurface.batchnumtriangles == 0)
11620 // batch debugging code
11621 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
11627 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
11628 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
11631 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
11633 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
11635 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
11636 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);
11643 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);
11646 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
11648 // pick the closest matching water plane
11649 int planeindex, vertexindex, bestplaneindex = -1;
11653 r_waterstate_waterplane_t *p;
11654 qboolean prepared = false;
11656 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
11658 if(p->camera_entity != rsurface.texture->camera_entity)
11663 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11665 if(rsurface.batchnumvertices == 0)
11668 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
11670 Matrix4x4_Transform(&rsurface.matrix, v, vert);
11671 d += fabs(PlaneDiff(vert, &p->plane));
11673 if (bestd > d || bestplaneindex < 0)
11676 bestplaneindex = planeindex;
11679 return bestplaneindex;
11680 // NOTE: this MAY return a totally unrelated water plane; we can ignore
11681 // this situation though, as it might be better to render single larger
11682 // batches with useless stuff (backface culled for example) than to
11683 // render multiple smaller batches
11686 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
11689 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11690 rsurface.passcolor4f_vertexbuffer = 0;
11691 rsurface.passcolor4f_bufferoffset = 0;
11692 for (i = 0;i < rsurface.batchnumvertices;i++)
11693 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
11696 static void RSurf_DrawBatch_GL11_ApplyFog(void)
11703 if (rsurface.passcolor4f)
11705 // generate color arrays
11706 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
11707 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11708 rsurface.passcolor4f_vertexbuffer = 0;
11709 rsurface.passcolor4f_bufferoffset = 0;
11710 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)
11712 f = RSurf_FogVertex(v);
11721 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11722 rsurface.passcolor4f_vertexbuffer = 0;
11723 rsurface.passcolor4f_bufferoffset = 0;
11724 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
11726 f = RSurf_FogVertex(v);
11735 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
11742 if (!rsurface.passcolor4f)
11744 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
11745 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11746 rsurface.passcolor4f_vertexbuffer = 0;
11747 rsurface.passcolor4f_bufferoffset = 0;
11748 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)
11750 f = RSurf_FogVertex(v);
11751 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
11752 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
11753 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
11758 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
11763 if (!rsurface.passcolor4f)
11765 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
11766 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11767 rsurface.passcolor4f_vertexbuffer = 0;
11768 rsurface.passcolor4f_bufferoffset = 0;
11769 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
11778 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
11783 if (!rsurface.passcolor4f)
11785 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
11786 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11787 rsurface.passcolor4f_vertexbuffer = 0;
11788 rsurface.passcolor4f_bufferoffset = 0;
11789 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
11791 c2[0] = c[0] + r_refdef.scene.ambient;
11792 c2[1] = c[1] + r_refdef.scene.ambient;
11793 c2[2] = c[2] + r_refdef.scene.ambient;
11798 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11801 rsurface.passcolor4f = NULL;
11802 rsurface.passcolor4f_vertexbuffer = 0;
11803 rsurface.passcolor4f_bufferoffset = 0;
11804 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
11805 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11806 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11807 GL_Color(r, g, b, a);
11808 R_Mesh_TexBind(0, rsurface.lightmaptexture);
11812 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11814 // TODO: optimize applyfog && applycolor case
11815 // just apply fog if necessary, and tint the fog color array if necessary
11816 rsurface.passcolor4f = NULL;
11817 rsurface.passcolor4f_vertexbuffer = 0;
11818 rsurface.passcolor4f_bufferoffset = 0;
11819 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
11820 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11821 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11822 GL_Color(r, g, b, a);
11826 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11829 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
11830 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
11831 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
11832 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
11833 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11834 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11835 GL_Color(r, g, b, a);
11839 static void RSurf_DrawBatch_GL11_ClampColor(void)
11844 if (!rsurface.passcolor4f)
11846 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
11848 c2[0] = bound(0.0f, c1[0], 1.0f);
11849 c2[1] = bound(0.0f, c1[1], 1.0f);
11850 c2[2] = bound(0.0f, c1[2], 1.0f);
11851 c2[3] = bound(0.0f, c1[3], 1.0f);
11855 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
11865 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11866 rsurface.passcolor4f_vertexbuffer = 0;
11867 rsurface.passcolor4f_bufferoffset = 0;
11868 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)
11870 f = -DotProduct(r_refdef.view.forward, n);
11872 f = f * 0.85 + 0.15; // work around so stuff won't get black
11873 f *= r_refdef.lightmapintensity;
11874 Vector4Set(c, f, f, f, 1);
11878 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11880 RSurf_DrawBatch_GL11_ApplyFakeLight();
11881 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
11882 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11883 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11884 GL_Color(r, g, b, a);
11888 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
11896 vec3_t ambientcolor;
11897 vec3_t diffusecolor;
11901 VectorCopy(rsurface.modellight_lightdir, lightdir);
11902 f = 0.5f * r_refdef.lightmapintensity;
11903 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
11904 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
11905 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
11906 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
11907 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
11908 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
11910 if (VectorLength2(diffusecolor) > 0)
11912 // q3-style directional shading
11913 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11914 rsurface.passcolor4f_vertexbuffer = 0;
11915 rsurface.passcolor4f_bufferoffset = 0;
11916 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)
11918 if ((f = DotProduct(n, lightdir)) > 0)
11919 VectorMA(ambientcolor, f, diffusecolor, c);
11921 VectorCopy(ambientcolor, c);
11928 *applycolor = false;
11932 *r = ambientcolor[0];
11933 *g = ambientcolor[1];
11934 *b = ambientcolor[2];
11935 rsurface.passcolor4f = NULL;
11936 rsurface.passcolor4f_vertexbuffer = 0;
11937 rsurface.passcolor4f_bufferoffset = 0;
11941 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11943 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
11944 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
11945 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11946 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11947 GL_Color(r, g, b, a);
11951 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
11957 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
11959 f = 1 - RSurf_FogVertex(v);
11967 void RSurf_SetupDepthAndCulling(void)
11969 // submodels are biased to avoid z-fighting with world surfaces that they
11970 // may be exactly overlapping (avoids z-fighting artifacts on certain
11971 // doors and things in Quake maps)
11972 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
11973 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
11974 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
11975 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11978 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11980 // transparent sky would be ridiculous
11981 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11983 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11984 skyrenderlater = true;
11985 RSurf_SetupDepthAndCulling();
11986 GL_DepthMask(true);
11987 // LordHavoc: HalfLife maps have freaky skypolys so don't use
11988 // skymasking on them, and Quake3 never did sky masking (unlike
11989 // software Quake and software Quake2), so disable the sky masking
11990 // in Quake3 maps as it causes problems with q3map2 sky tricks,
11991 // and skymasking also looks very bad when noclipping outside the
11992 // level, so don't use it then either.
11993 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
11995 R_Mesh_ResetTextureState();
11996 if (skyrendermasked)
11998 R_SetupShader_DepthOrShadow();
11999 // depth-only (masking)
12000 GL_ColorMask(0,0,0,0);
12001 // just to make sure that braindead drivers don't draw
12002 // anything despite that colormask...
12003 GL_BlendFunc(GL_ZERO, GL_ONE);
12004 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12005 if (rsurface.batchvertex3fbuffer)
12006 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
12008 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
12012 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12014 GL_BlendFunc(GL_ONE, GL_ZERO);
12015 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12016 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
12017 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12020 if (skyrendermasked)
12021 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12023 R_Mesh_ResetTextureState();
12024 GL_Color(1, 1, 1, 1);
12027 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
12028 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
12029 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12031 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
12035 // render screenspace normalmap to texture
12036 GL_DepthMask(true);
12037 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
12042 // bind lightmap texture
12044 // water/refraction/reflection/camera surfaces have to be handled specially
12045 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
12047 int start, end, startplaneindex;
12048 for (start = 0;start < texturenumsurfaces;start = end)
12050 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
12051 if(startplaneindex < 0)
12053 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
12054 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
12058 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
12060 // now that we have a batch using the same planeindex, render it
12061 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
12063 // render water or distortion background
12064 GL_DepthMask(true);
12065 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));
12067 // blend surface on top
12068 GL_DepthMask(false);
12069 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
12072 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
12074 // render surface with reflection texture as input
12075 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12076 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));
12083 // render surface batch normally
12084 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12085 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
12089 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12091 // OpenGL 1.3 path - anything not completely ancient
12092 qboolean applycolor;
12095 const texturelayer_t *layer;
12096 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);
12097 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12099 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12102 int layertexrgbscale;
12103 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12105 if (layerindex == 0)
12106 GL_AlphaTest(true);
12109 GL_AlphaTest(false);
12110 GL_DepthFunc(GL_EQUAL);
12113 GL_DepthMask(layer->depthmask && writedepth);
12114 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12115 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
12117 layertexrgbscale = 4;
12118 VectorScale(layer->color, 0.25f, layercolor);
12120 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
12122 layertexrgbscale = 2;
12123 VectorScale(layer->color, 0.5f, layercolor);
12127 layertexrgbscale = 1;
12128 VectorScale(layer->color, 1.0f, layercolor);
12130 layercolor[3] = layer->color[3];
12131 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
12132 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12133 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12134 switch (layer->type)
12136 case TEXTURELAYERTYPE_LITTEXTURE:
12137 // single-pass lightmapped texture with 2x rgbscale
12138 R_Mesh_TexBind(0, r_texture_white);
12139 R_Mesh_TexMatrix(0, NULL);
12140 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12141 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12142 R_Mesh_TexBind(1, layer->texture);
12143 R_Mesh_TexMatrix(1, &layer->texmatrix);
12144 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12145 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12146 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12147 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12148 else if (FAKELIGHT_ENABLED)
12149 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12150 else if (rsurface.uselightmaptexture)
12151 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12153 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12155 case TEXTURELAYERTYPE_TEXTURE:
12156 // singletexture unlit texture with transparency support
12157 R_Mesh_TexBind(0, layer->texture);
12158 R_Mesh_TexMatrix(0, &layer->texmatrix);
12159 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12160 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12161 R_Mesh_TexBind(1, 0);
12162 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12163 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12165 case TEXTURELAYERTYPE_FOG:
12166 // singletexture fogging
12167 if (layer->texture)
12169 R_Mesh_TexBind(0, layer->texture);
12170 R_Mesh_TexMatrix(0, &layer->texmatrix);
12171 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12172 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12176 R_Mesh_TexBind(0, 0);
12177 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12179 R_Mesh_TexBind(1, 0);
12180 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12181 // generate a color array for the fog pass
12182 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
12183 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
12187 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12190 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12192 GL_DepthFunc(GL_LEQUAL);
12193 GL_AlphaTest(false);
12197 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12199 // OpenGL 1.1 - crusty old voodoo path
12202 const texturelayer_t *layer;
12203 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);
12204 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12206 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12208 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12210 if (layerindex == 0)
12211 GL_AlphaTest(true);
12214 GL_AlphaTest(false);
12215 GL_DepthFunc(GL_EQUAL);
12218 GL_DepthMask(layer->depthmask && writedepth);
12219 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12220 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12221 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12222 switch (layer->type)
12224 case TEXTURELAYERTYPE_LITTEXTURE:
12225 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
12227 // two-pass lit texture with 2x rgbscale
12228 // first the lightmap pass
12229 R_Mesh_TexBind(0, r_texture_white);
12230 R_Mesh_TexMatrix(0, NULL);
12231 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12232 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12233 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12234 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
12235 else if (FAKELIGHT_ENABLED)
12236 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
12237 else if (rsurface.uselightmaptexture)
12238 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
12240 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
12241 // then apply the texture to it
12242 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
12243 R_Mesh_TexBind(0, layer->texture);
12244 R_Mesh_TexMatrix(0, &layer->texmatrix);
12245 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12246 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12247 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);
12251 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
12252 R_Mesh_TexBind(0, layer->texture);
12253 R_Mesh_TexMatrix(0, &layer->texmatrix);
12254 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12255 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12256 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12257 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);
12259 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);
12262 case TEXTURELAYERTYPE_TEXTURE:
12263 // singletexture unlit texture with transparency support
12264 R_Mesh_TexBind(0, layer->texture);
12265 R_Mesh_TexMatrix(0, &layer->texmatrix);
12266 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12267 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12268 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);
12270 case TEXTURELAYERTYPE_FOG:
12271 // singletexture fogging
12272 if (layer->texture)
12274 R_Mesh_TexBind(0, layer->texture);
12275 R_Mesh_TexMatrix(0, &layer->texmatrix);
12276 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12277 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12281 R_Mesh_TexBind(0, 0);
12282 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12284 // generate a color array for the fog pass
12285 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
12286 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
12290 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12293 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12295 GL_DepthFunc(GL_LEQUAL);
12296 GL_AlphaTest(false);
12300 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12304 r_vertexgeneric_t *batchvertex;
12307 // R_Mesh_ResetTextureState();
12308 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12310 if(rsurface.texture && rsurface.texture->currentskinframe)
12312 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
12313 c[3] *= rsurface.texture->currentalpha;
12323 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
12325 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
12326 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
12327 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
12330 // brighten it up (as texture value 127 means "unlit")
12331 c[0] *= 2 * r_refdef.view.colorscale;
12332 c[1] *= 2 * r_refdef.view.colorscale;
12333 c[2] *= 2 * r_refdef.view.colorscale;
12335 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
12336 c[3] *= r_wateralpha.value;
12338 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
12340 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12341 GL_DepthMask(false);
12343 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
12345 GL_BlendFunc(GL_ONE, GL_ONE);
12346 GL_DepthMask(false);
12348 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12350 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
12351 GL_DepthMask(false);
12353 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
12355 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
12356 GL_DepthMask(false);
12360 GL_BlendFunc(GL_ONE, GL_ZERO);
12361 GL_DepthMask(writedepth);
12364 if (r_showsurfaces.integer == 3)
12366 rsurface.passcolor4f = NULL;
12368 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
12370 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12372 rsurface.passcolor4f = NULL;
12373 rsurface.passcolor4f_vertexbuffer = 0;
12374 rsurface.passcolor4f_bufferoffset = 0;
12376 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12378 qboolean applycolor = true;
12381 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12383 r_refdef.lightmapintensity = 1;
12384 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
12385 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12387 else if (FAKELIGHT_ENABLED)
12389 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12391 r_refdef.lightmapintensity = r_fakelight_intensity.value;
12392 RSurf_DrawBatch_GL11_ApplyFakeLight();
12393 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12397 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12399 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12400 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12401 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12404 if(!rsurface.passcolor4f)
12405 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
12407 RSurf_DrawBatch_GL11_ApplyAmbient();
12408 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
12409 if(r_refdef.fogenabled)
12410 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
12411 RSurf_DrawBatch_GL11_ClampColor();
12413 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
12414 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12417 else if (!r_refdef.view.showdebug)
12419 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12420 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12421 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12423 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12424 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
12426 R_Mesh_PrepareVertices_Generic_Unlock();
12429 else if (r_showsurfaces.integer == 4)
12431 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12432 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12433 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12435 unsigned char c = (vi << 3) * (1.0f / 256.0f);
12436 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12437 Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
12439 R_Mesh_PrepareVertices_Generic_Unlock();
12442 else if (r_showsurfaces.integer == 2)
12445 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12446 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
12447 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
12449 unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
12450 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
12451 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
12452 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
12453 Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
12454 Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
12455 Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
12457 R_Mesh_PrepareVertices_Generic_Unlock();
12458 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
12462 int texturesurfaceindex;
12464 const msurface_t *surface;
12465 float surfacecolor4f[4];
12466 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12467 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
12469 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
12471 surface = texturesurfacelist[texturesurfaceindex];
12472 k = (int)(((size_t)surface) / sizeof(msurface_t));
12473 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
12474 for (j = 0;j < surface->num_vertices;j++)
12476 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12477 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
12481 R_Mesh_PrepareVertices_Generic_Unlock();
12486 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12489 RSurf_SetupDepthAndCulling();
12490 if (r_showsurfaces.integer)
12492 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12495 switch (vid.renderpath)
12497 case RENDERPATH_GL20:
12498 case RENDERPATH_D3D9:
12499 case RENDERPATH_D3D10:
12500 case RENDERPATH_D3D11:
12501 case RENDERPATH_SOFT:
12502 case RENDERPATH_GLES2:
12503 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12505 case RENDERPATH_GL13:
12506 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
12508 case RENDERPATH_GL11:
12509 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
12515 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12518 RSurf_SetupDepthAndCulling();
12519 if (r_showsurfaces.integer)
12521 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12524 switch (vid.renderpath)
12526 case RENDERPATH_GL20:
12527 case RENDERPATH_D3D9:
12528 case RENDERPATH_D3D10:
12529 case RENDERPATH_D3D11:
12530 case RENDERPATH_SOFT:
12531 case RENDERPATH_GLES2:
12532 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12534 case RENDERPATH_GL13:
12535 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
12537 case RENDERPATH_GL11:
12538 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
12544 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
12547 int texturenumsurfaces, endsurface;
12548 texture_t *texture;
12549 const msurface_t *surface;
12550 #define MAXBATCH_TRANSPARENTSURFACES 256
12551 const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
12553 // if the model is static it doesn't matter what value we give for
12554 // wantnormals and wanttangents, so this logic uses only rules applicable
12555 // to a model, knowing that they are meaningless otherwise
12556 if (ent == r_refdef.scene.worldentity)
12557 RSurf_ActiveWorldEntity();
12558 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12559 RSurf_ActiveModelEntity(ent, false, false, false);
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 RSurf_ActiveModelEntity(ent, true, true, false);
12572 case RENDERPATH_GL13:
12573 case RENDERPATH_GL11:
12574 RSurf_ActiveModelEntity(ent, true, false, false);
12579 if (r_transparentdepthmasking.integer)
12581 qboolean setup = false;
12582 for (i = 0;i < numsurfaces;i = j)
12585 surface = rsurface.modelsurfaces + surfacelist[i];
12586 texture = surface->texture;
12587 rsurface.texture = R_GetCurrentTexture(texture);
12588 rsurface.lightmaptexture = NULL;
12589 rsurface.deluxemaptexture = NULL;
12590 rsurface.uselightmaptexture = false;
12591 // scan ahead until we find a different texture
12592 endsurface = min(i + 1024, numsurfaces);
12593 texturenumsurfaces = 0;
12594 texturesurfacelist[texturenumsurfaces++] = surface;
12595 for (;j < endsurface;j++)
12597 surface = rsurface.modelsurfaces + surfacelist[j];
12598 if (texture != surface->texture)
12600 texturesurfacelist[texturenumsurfaces++] = surface;
12602 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
12604 // render the range of surfaces as depth
12608 GL_ColorMask(0,0,0,0);
12610 GL_DepthTest(true);
12611 GL_BlendFunc(GL_ONE, GL_ZERO);
12612 GL_DepthMask(true);
12613 // R_Mesh_ResetTextureState();
12614 R_SetupShader_DepthOrShadow();
12616 RSurf_SetupDepthAndCulling();
12617 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
12618 if (rsurface.batchvertex3fbuffer)
12619 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
12621 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
12625 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12628 for (i = 0;i < numsurfaces;i = j)
12631 surface = rsurface.modelsurfaces + surfacelist[i];
12632 texture = surface->texture;
12633 rsurface.texture = R_GetCurrentTexture(texture);
12634 // scan ahead until we find a different texture
12635 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
12636 texturenumsurfaces = 0;
12637 texturesurfacelist[texturenumsurfaces++] = surface;
12638 if(FAKELIGHT_ENABLED)
12640 rsurface.lightmaptexture = NULL;
12641 rsurface.deluxemaptexture = NULL;
12642 rsurface.uselightmaptexture = false;
12643 for (;j < endsurface;j++)
12645 surface = rsurface.modelsurfaces + surfacelist[j];
12646 if (texture != surface->texture)
12648 texturesurfacelist[texturenumsurfaces++] = surface;
12653 rsurface.lightmaptexture = surface->lightmaptexture;
12654 rsurface.deluxemaptexture = surface->deluxemaptexture;
12655 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
12656 for (;j < endsurface;j++)
12658 surface = rsurface.modelsurfaces + surfacelist[j];
12659 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
12661 texturesurfacelist[texturenumsurfaces++] = surface;
12664 // render the range of surfaces
12665 if (ent == r_refdef.scene.worldentity)
12666 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
12668 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
12670 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12673 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
12675 // transparent surfaces get pushed off into the transparent queue
12676 int surfacelistindex;
12677 const msurface_t *surface;
12678 vec3_t tempcenter, center;
12679 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
12681 surface = texturesurfacelist[surfacelistindex];
12682 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
12683 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
12684 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
12685 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
12686 if (queueentity->transparent_offset) // transparent offset
12688 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
12689 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
12690 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
12692 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
12696 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12698 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
12700 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
12702 RSurf_SetupDepthAndCulling();
12703 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
12704 if (rsurface.batchvertex3fbuffer)
12705 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
12707 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
12711 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
12713 const entity_render_t *queueentity = r_refdef.scene.worldentity;
12716 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
12719 if (!rsurface.texture->currentnumlayers)
12721 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12722 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12724 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12726 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
12727 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
12728 else if (!rsurface.texture->currentnumlayers)
12730 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
12732 // in the deferred case, transparent surfaces were queued during prepass
12733 if (!r_shadow_usingdeferredprepass)
12734 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12738 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
12739 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
12744 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
12747 texture_t *texture;
12748 R_FrameData_SetMark();
12749 // break the surface list down into batches by texture and use of lightmapping
12750 for (i = 0;i < numsurfaces;i = j)
12753 // texture is the base texture pointer, rsurface.texture is the
12754 // current frame/skin the texture is directing us to use (for example
12755 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
12756 // use skin 1 instead)
12757 texture = surfacelist[i]->texture;
12758 rsurface.texture = R_GetCurrentTexture(texture);
12759 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
12761 // if this texture is not the kind we want, skip ahead to the next one
12762 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12766 if(FAKELIGHT_ENABLED || depthonly || prepass)
12768 rsurface.lightmaptexture = NULL;
12769 rsurface.deluxemaptexture = NULL;
12770 rsurface.uselightmaptexture = false;
12771 // simply scan ahead until we find a different texture or lightmap state
12772 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12777 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
12778 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
12779 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
12780 // simply scan ahead until we find a different texture or lightmap state
12781 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
12784 // render the range of surfaces
12785 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
12787 R_FrameData_ReturnToMark();
12790 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
12794 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
12797 if (!rsurface.texture->currentnumlayers)
12799 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12800 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12802 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12804 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
12805 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
12806 else if (!rsurface.texture->currentnumlayers)
12808 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
12810 // in the deferred case, transparent surfaces were queued during prepass
12811 if (!r_shadow_usingdeferredprepass)
12812 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12816 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
12817 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
12822 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
12825 texture_t *texture;
12826 R_FrameData_SetMark();
12827 // break the surface list down into batches by texture and use of lightmapping
12828 for (i = 0;i < numsurfaces;i = j)
12831 // texture is the base texture pointer, rsurface.texture is the
12832 // current frame/skin the texture is directing us to use (for example
12833 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
12834 // use skin 1 instead)
12835 texture = surfacelist[i]->texture;
12836 rsurface.texture = R_GetCurrentTexture(texture);
12837 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
12839 // if this texture is not the kind we want, skip ahead to the next one
12840 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12844 if(FAKELIGHT_ENABLED || depthonly || prepass)
12846 rsurface.lightmaptexture = NULL;
12847 rsurface.deluxemaptexture = NULL;
12848 rsurface.uselightmaptexture = false;
12849 // simply scan ahead until we find a different texture or lightmap state
12850 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12855 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
12856 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
12857 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
12858 // simply scan ahead until we find a different texture or lightmap state
12859 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
12862 // render the range of surfaces
12863 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
12865 R_FrameData_ReturnToMark();
12868 float locboxvertex3f[6*4*3] =
12870 1,0,1, 1,0,0, 1,1,0, 1,1,1,
12871 0,1,1, 0,1,0, 0,0,0, 0,0,1,
12872 1,1,1, 1,1,0, 0,1,0, 0,1,1,
12873 0,0,1, 0,0,0, 1,0,0, 1,0,1,
12874 0,0,1, 1,0,1, 1,1,1, 0,1,1,
12875 1,0,0, 0,0,0, 0,1,0, 1,1,0
12878 unsigned short locboxelements[6*2*3] =
12883 12,13,14, 12,14,15,
12884 16,17,18, 16,18,19,
12888 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
12891 cl_locnode_t *loc = (cl_locnode_t *)ent;
12893 float vertex3f[6*4*3];
12895 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12896 GL_DepthMask(false);
12897 GL_DepthRange(0, 1);
12898 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12899 GL_DepthTest(true);
12900 GL_CullFace(GL_NONE);
12901 R_EntityMatrix(&identitymatrix);
12903 // R_Mesh_ResetTextureState();
12905 i = surfacelist[0];
12906 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12907 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12908 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12909 surfacelist[0] < 0 ? 0.5f : 0.125f);
12911 if (VectorCompare(loc->mins, loc->maxs))
12913 VectorSet(size, 2, 2, 2);
12914 VectorMA(loc->mins, -0.5f, size, mins);
12918 VectorCopy(loc->mins, mins);
12919 VectorSubtract(loc->maxs, loc->mins, size);
12922 for (i = 0;i < 6*4*3;)
12923 for (j = 0;j < 3;j++, i++)
12924 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
12926 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
12927 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12928 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
12931 void R_DrawLocs(void)
12934 cl_locnode_t *loc, *nearestloc;
12936 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
12937 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
12939 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
12940 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
12944 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
12946 if (decalsystem->decals)
12947 Mem_Free(decalsystem->decals);
12948 memset(decalsystem, 0, sizeof(*decalsystem));
12951 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)
12954 tridecal_t *decals;
12957 // expand or initialize the system
12958 if (decalsystem->maxdecals <= decalsystem->numdecals)
12960 decalsystem_t old = *decalsystem;
12961 qboolean useshortelements;
12962 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
12963 useshortelements = decalsystem->maxdecals * 3 <= 65536;
12964 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)));
12965 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
12966 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
12967 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
12968 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
12969 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
12970 if (decalsystem->numdecals)
12971 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
12973 Mem_Free(old.decals);
12974 for (i = 0;i < decalsystem->maxdecals*3;i++)
12975 decalsystem->element3i[i] = i;
12976 if (useshortelements)
12977 for (i = 0;i < decalsystem->maxdecals*3;i++)
12978 decalsystem->element3s[i] = i;
12981 // grab a decal and search for another free slot for the next one
12982 decals = decalsystem->decals;
12983 decal = decalsystem->decals + (i = decalsystem->freedecal++);
12984 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
12986 decalsystem->freedecal = i;
12987 if (decalsystem->numdecals <= i)
12988 decalsystem->numdecals = i + 1;
12990 // initialize the decal
12992 decal->triangleindex = triangleindex;
12993 decal->surfaceindex = surfaceindex;
12994 decal->decalsequence = decalsequence;
12995 decal->color4f[0][0] = c0[0];
12996 decal->color4f[0][1] = c0[1];
12997 decal->color4f[0][2] = c0[2];
12998 decal->color4f[0][3] = 1;
12999 decal->color4f[1][0] = c1[0];
13000 decal->color4f[1][1] = c1[1];
13001 decal->color4f[1][2] = c1[2];
13002 decal->color4f[1][3] = 1;
13003 decal->color4f[2][0] = c2[0];
13004 decal->color4f[2][1] = c2[1];
13005 decal->color4f[2][2] = c2[2];
13006 decal->color4f[2][3] = 1;
13007 decal->vertex3f[0][0] = v0[0];
13008 decal->vertex3f[0][1] = v0[1];
13009 decal->vertex3f[0][2] = v0[2];
13010 decal->vertex3f[1][0] = v1[0];
13011 decal->vertex3f[1][1] = v1[1];
13012 decal->vertex3f[1][2] = v1[2];
13013 decal->vertex3f[2][0] = v2[0];
13014 decal->vertex3f[2][1] = v2[1];
13015 decal->vertex3f[2][2] = v2[2];
13016 decal->texcoord2f[0][0] = t0[0];
13017 decal->texcoord2f[0][1] = t0[1];
13018 decal->texcoord2f[1][0] = t1[0];
13019 decal->texcoord2f[1][1] = t1[1];
13020 decal->texcoord2f[2][0] = t2[0];
13021 decal->texcoord2f[2][1] = t2[1];
13024 extern cvar_t cl_decals_bias;
13025 extern cvar_t cl_decals_models;
13026 extern cvar_t cl_decals_newsystem_intensitymultiplier;
13027 // baseparms, parms, temps
13028 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)
13033 const float *vertex3f;
13034 const float *normal3f;
13036 float points[2][9][3];
13043 e = rsurface.modelelement3i + 3*triangleindex;
13045 vertex3f = rsurface.modelvertex3f;
13046 normal3f = rsurface.modelnormal3f;
13048 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13050 index = 3*e[cornerindex];
13051 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
13054 //TriangleNormal(v[0], v[1], v[2], normal);
13055 //if (DotProduct(normal, localnormal) < 0.0f)
13057 // clip by each of the box planes formed from the projection matrix
13058 // if anything survives, we emit the decal
13059 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]);
13062 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]);
13065 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]);
13068 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]);
13071 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]);
13074 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]);
13077 // some part of the triangle survived, so we have to accept it...
13080 // dynamic always uses the original triangle
13082 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13084 index = 3*e[cornerindex];
13085 VectorCopy(vertex3f + index, v[cornerindex]);
13088 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
13090 // convert vertex positions to texcoords
13091 Matrix4x4_Transform(projection, v[cornerindex], temp);
13092 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
13093 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
13094 // calculate distance fade from the projection origin
13095 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
13096 f = bound(0.0f, f, 1.0f);
13097 c[cornerindex][0] = r * f;
13098 c[cornerindex][1] = g * f;
13099 c[cornerindex][2] = b * f;
13100 c[cornerindex][3] = 1.0f;
13101 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
13104 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);
13106 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
13107 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);
13109 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)
13111 matrix4x4_t projection;
13112 decalsystem_t *decalsystem;
13115 const msurface_t *surface;
13116 const msurface_t *surfaces;
13117 const int *surfacelist;
13118 const texture_t *texture;
13120 int numsurfacelist;
13121 int surfacelistindex;
13124 float localorigin[3];
13125 float localnormal[3];
13126 float localmins[3];
13127 float localmaxs[3];
13130 float planes[6][4];
13133 int bih_triangles_count;
13134 int bih_triangles[256];
13135 int bih_surfaces[256];
13137 decalsystem = &ent->decalsystem;
13138 model = ent->model;
13139 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
13141 R_DecalSystem_Reset(&ent->decalsystem);
13145 if (!model->brush.data_leafs && !cl_decals_models.integer)
13147 if (decalsystem->model)
13148 R_DecalSystem_Reset(decalsystem);
13152 if (decalsystem->model != model)
13153 R_DecalSystem_Reset(decalsystem);
13154 decalsystem->model = model;
13156 RSurf_ActiveModelEntity(ent, true, false, false);
13158 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
13159 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
13160 VectorNormalize(localnormal);
13161 localsize = worldsize*rsurface.inversematrixscale;
13162 localmins[0] = localorigin[0] - localsize;
13163 localmins[1] = localorigin[1] - localsize;
13164 localmins[2] = localorigin[2] - localsize;
13165 localmaxs[0] = localorigin[0] + localsize;
13166 localmaxs[1] = localorigin[1] + localsize;
13167 localmaxs[2] = localorigin[2] + localsize;
13169 //VectorCopy(localnormal, planes[4]);
13170 //VectorVectors(planes[4], planes[2], planes[0]);
13171 AnglesFromVectors(angles, localnormal, NULL, false);
13172 AngleVectors(angles, planes[0], planes[2], planes[4]);
13173 VectorNegate(planes[0], planes[1]);
13174 VectorNegate(planes[2], planes[3]);
13175 VectorNegate(planes[4], planes[5]);
13176 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
13177 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
13178 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
13179 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
13180 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
13181 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
13186 matrix4x4_t forwardprojection;
13187 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
13188 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
13193 float projectionvector[4][3];
13194 VectorScale(planes[0], ilocalsize, projectionvector[0]);
13195 VectorScale(planes[2], ilocalsize, projectionvector[1]);
13196 VectorScale(planes[4], ilocalsize, projectionvector[2]);
13197 projectionvector[0][0] = planes[0][0] * ilocalsize;
13198 projectionvector[0][1] = planes[1][0] * ilocalsize;
13199 projectionvector[0][2] = planes[2][0] * ilocalsize;
13200 projectionvector[1][0] = planes[0][1] * ilocalsize;
13201 projectionvector[1][1] = planes[1][1] * ilocalsize;
13202 projectionvector[1][2] = planes[2][1] * ilocalsize;
13203 projectionvector[2][0] = planes[0][2] * ilocalsize;
13204 projectionvector[2][1] = planes[1][2] * ilocalsize;
13205 projectionvector[2][2] = planes[2][2] * ilocalsize;
13206 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
13207 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
13208 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
13209 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
13213 dynamic = model->surfmesh.isanimated;
13214 numsurfacelist = model->nummodelsurfaces;
13215 surfacelist = model->sortedmodelsurfaces;
13216 surfaces = model->data_surfaces;
13219 bih_triangles_count = -1;
13222 if(model->render_bih.numleafs)
13223 bih = &model->render_bih;
13224 else if(model->collision_bih.numleafs)
13225 bih = &model->collision_bih;
13228 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
13229 if(bih_triangles_count == 0)
13231 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
13233 if(bih_triangles_count > 0)
13235 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
13237 surfaceindex = bih_surfaces[triangleindex];
13238 surface = surfaces + surfaceindex;
13239 texture = surface->texture;
13240 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13242 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13244 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
13249 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
13251 surfaceindex = surfacelist[surfacelistindex];
13252 surface = surfaces + surfaceindex;
13253 // check cull box first because it rejects more than any other check
13254 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
13256 // skip transparent surfaces
13257 texture = surface->texture;
13258 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13260 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13262 numtriangles = surface->num_triangles;
13263 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
13264 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
13269 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
13270 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)
13272 int renderentityindex;
13273 float worldmins[3];
13274 float worldmaxs[3];
13275 entity_render_t *ent;
13277 if (!cl_decals_newsystem.integer)
13280 worldmins[0] = worldorigin[0] - worldsize;
13281 worldmins[1] = worldorigin[1] - worldsize;
13282 worldmins[2] = worldorigin[2] - worldsize;
13283 worldmaxs[0] = worldorigin[0] + worldsize;
13284 worldmaxs[1] = worldorigin[1] + worldsize;
13285 worldmaxs[2] = worldorigin[2] + worldsize;
13287 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13289 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
13291 ent = r_refdef.scene.entities[renderentityindex];
13292 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
13295 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13299 typedef struct r_decalsystem_splatqueue_s
13301 vec3_t worldorigin;
13302 vec3_t worldnormal;
13308 r_decalsystem_splatqueue_t;
13310 int r_decalsystem_numqueued = 0;
13311 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
13313 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)
13315 r_decalsystem_splatqueue_t *queue;
13317 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
13320 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
13321 VectorCopy(worldorigin, queue->worldorigin);
13322 VectorCopy(worldnormal, queue->worldnormal);
13323 Vector4Set(queue->color, r, g, b, a);
13324 Vector4Set(queue->tcrange, s1, t1, s2, t2);
13325 queue->worldsize = worldsize;
13326 queue->decalsequence = cl.decalsequence++;
13329 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
13332 r_decalsystem_splatqueue_t *queue;
13334 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
13335 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);
13336 r_decalsystem_numqueued = 0;
13339 extern cvar_t cl_decals_max;
13340 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
13343 decalsystem_t *decalsystem = &ent->decalsystem;
13350 if (!decalsystem->numdecals)
13353 if (r_showsurfaces.integer)
13356 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13358 R_DecalSystem_Reset(decalsystem);
13362 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
13363 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
13365 if (decalsystem->lastupdatetime)
13366 frametime = (cl.time - decalsystem->lastupdatetime);
13369 decalsystem->lastupdatetime = cl.time;
13370 decal = decalsystem->decals;
13371 numdecals = decalsystem->numdecals;
13373 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13375 if (decal->color4f[0][3])
13377 decal->lived += frametime;
13378 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
13380 memset(decal, 0, sizeof(*decal));
13381 if (decalsystem->freedecal > i)
13382 decalsystem->freedecal = i;
13386 decal = decalsystem->decals;
13387 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
13390 // collapse the array by shuffling the tail decals into the gaps
13393 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
13394 decalsystem->freedecal++;
13395 if (decalsystem->freedecal == numdecals)
13397 decal[decalsystem->freedecal] = decal[--numdecals];
13400 decalsystem->numdecals = numdecals;
13402 if (numdecals <= 0)
13404 // if there are no decals left, reset decalsystem
13405 R_DecalSystem_Reset(decalsystem);
13409 extern skinframe_t *decalskinframe;
13410 static void R_DrawModelDecals_Entity(entity_render_t *ent)
13413 decalsystem_t *decalsystem = &ent->decalsystem;
13422 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
13425 numdecals = decalsystem->numdecals;
13429 if (r_showsurfaces.integer)
13432 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13434 R_DecalSystem_Reset(decalsystem);
13438 // if the model is static it doesn't matter what value we give for
13439 // wantnormals and wanttangents, so this logic uses only rules applicable
13440 // to a model, knowing that they are meaningless otherwise
13441 if (ent == r_refdef.scene.worldentity)
13442 RSurf_ActiveWorldEntity();
13444 RSurf_ActiveModelEntity(ent, false, false, false);
13446 decalsystem->lastupdatetime = cl.time;
13447 decal = decalsystem->decals;
13449 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
13451 // update vertex positions for animated models
13452 v3f = decalsystem->vertex3f;
13453 c4f = decalsystem->color4f;
13454 t2f = decalsystem->texcoord2f;
13455 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13457 if (!decal->color4f[0][3])
13460 if (surfacevisible && !surfacevisible[decal->surfaceindex])
13463 // update color values for fading decals
13464 if (decal->lived >= cl_decals_time.value)
13465 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
13469 c4f[ 0] = decal->color4f[0][0] * alpha;
13470 c4f[ 1] = decal->color4f[0][1] * alpha;
13471 c4f[ 2] = decal->color4f[0][2] * alpha;
13473 c4f[ 4] = decal->color4f[1][0] * alpha;
13474 c4f[ 5] = decal->color4f[1][1] * alpha;
13475 c4f[ 6] = decal->color4f[1][2] * alpha;
13477 c4f[ 8] = decal->color4f[2][0] * alpha;
13478 c4f[ 9] = decal->color4f[2][1] * alpha;
13479 c4f[10] = decal->color4f[2][2] * alpha;
13482 t2f[0] = decal->texcoord2f[0][0];
13483 t2f[1] = decal->texcoord2f[0][1];
13484 t2f[2] = decal->texcoord2f[1][0];
13485 t2f[3] = decal->texcoord2f[1][1];
13486 t2f[4] = decal->texcoord2f[2][0];
13487 t2f[5] = decal->texcoord2f[2][1];
13489 // update vertex positions for animated models
13490 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
13492 e = rsurface.modelelement3i + 3*decal->triangleindex;
13493 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
13494 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
13495 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
13499 VectorCopy(decal->vertex3f[0], v3f);
13500 VectorCopy(decal->vertex3f[1], v3f + 3);
13501 VectorCopy(decal->vertex3f[2], v3f + 6);
13504 if (r_refdef.fogenabled)
13506 alpha = RSurf_FogVertex(v3f);
13507 VectorScale(c4f, alpha, c4f);
13508 alpha = RSurf_FogVertex(v3f + 3);
13509 VectorScale(c4f + 4, alpha, c4f + 4);
13510 alpha = RSurf_FogVertex(v3f + 6);
13511 VectorScale(c4f + 8, alpha, c4f + 8);
13522 r_refdef.stats.drawndecals += numtris;
13524 // now render the decals all at once
13525 // (this assumes they all use one particle font texture!)
13526 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);
13527 // R_Mesh_ResetTextureState();
13528 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
13529 GL_DepthMask(false);
13530 GL_DepthRange(0, 1);
13531 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
13532 GL_DepthTest(true);
13533 GL_CullFace(GL_NONE);
13534 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
13535 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
13536 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
13540 static void R_DrawModelDecals(void)
13544 // fade faster when there are too many decals
13545 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
13546 for (i = 0;i < r_refdef.scene.numentities;i++)
13547 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
13549 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
13550 for (i = 0;i < r_refdef.scene.numentities;i++)
13551 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
13552 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
13554 R_DecalSystem_ApplySplatEntitiesQueue();
13556 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
13557 for (i = 0;i < r_refdef.scene.numentities;i++)
13558 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
13560 r_refdef.stats.totaldecals += numdecals;
13562 if (r_showsurfaces.integer)
13565 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
13567 for (i = 0;i < r_refdef.scene.numentities;i++)
13569 if (!r_refdef.viewcache.entityvisible[i])
13571 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
13572 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
13576 extern cvar_t mod_collision_bih;
13577 void R_DrawDebugModel(void)
13579 entity_render_t *ent = rsurface.entity;
13580 int i, j, k, l, flagsmask;
13581 const msurface_t *surface;
13582 dp_model_t *model = ent->model;
13585 switch(vid.renderpath)
13587 case RENDERPATH_GL11:
13588 case RENDERPATH_GL13:
13589 case RENDERPATH_GL20:
13591 case RENDERPATH_D3D9:
13592 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13594 case RENDERPATH_D3D10:
13595 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13597 case RENDERPATH_D3D11:
13598 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13600 case RENDERPATH_SOFT:
13601 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13603 case RENDERPATH_GLES2:
13604 //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13608 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
13610 // R_Mesh_ResetTextureState();
13611 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13612 GL_DepthRange(0, 1);
13613 GL_DepthTest(!r_showdisabledepthtest.integer);
13614 GL_DepthMask(false);
13615 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13617 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
13621 qboolean cullbox = ent == r_refdef.scene.worldentity;
13622 const q3mbrush_t *brush;
13623 const bih_t *bih = &model->collision_bih;
13624 const bih_leaf_t *bihleaf;
13625 float vertex3f[3][3];
13626 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
13628 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
13630 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
13632 switch (bihleaf->type)
13635 brush = model->brush.data_brushes + bihleaf->itemindex;
13636 if (brush->colbrushf && brush->colbrushf->numtriangles)
13638 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);
13639 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
13640 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
13643 case BIH_COLLISIONTRIANGLE:
13644 triangleindex = bihleaf->itemindex;
13645 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
13646 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
13647 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
13648 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);
13649 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
13650 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
13652 case BIH_RENDERTRIANGLE:
13653 triangleindex = bihleaf->itemindex;
13654 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
13655 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
13656 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
13657 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);
13658 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
13659 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
13665 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13667 if (r_showtris.integer || (r_shownormals.value != 0))
13669 if (r_showdisabledepthtest.integer)
13671 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13672 GL_DepthMask(false);
13676 GL_BlendFunc(GL_ONE, GL_ZERO);
13677 GL_DepthMask(true);
13679 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
13681 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
13683 rsurface.texture = R_GetCurrentTexture(surface->texture);
13684 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
13686 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
13687 if (r_showtris.value > 0)
13689 if (!rsurface.texture->currentlayers->depthmask)
13690 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
13691 else if (ent == r_refdef.scene.worldentity)
13692 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
13694 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
13695 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
13696 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
13698 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
13701 if (r_shownormals.value < 0)
13703 qglBegin(GL_LINES);
13704 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
13706 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13707 GL_Color(0, 0, r_refdef.view.colorscale, 1);
13708 qglVertex3f(v[0], v[1], v[2]);
13709 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
13710 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
13711 qglVertex3f(v[0], v[1], v[2]);
13716 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
13718 qglBegin(GL_LINES);
13719 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
13721 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13722 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
13723 qglVertex3f(v[0], v[1], v[2]);
13724 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
13725 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
13726 qglVertex3f(v[0], v[1], v[2]);
13730 qglBegin(GL_LINES);
13731 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
13733 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13734 GL_Color(0, r_refdef.view.colorscale, 0, 1);
13735 qglVertex3f(v[0], v[1], v[2]);
13736 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
13737 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
13738 qglVertex3f(v[0], v[1], v[2]);
13742 qglBegin(GL_LINES);
13743 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
13745 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13746 GL_Color(0, 0, r_refdef.view.colorscale, 1);
13747 qglVertex3f(v[0], v[1], v[2]);
13748 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
13749 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
13750 qglVertex3f(v[0], v[1], v[2]);
13757 rsurface.texture = NULL;
13761 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
13762 int r_maxsurfacelist = 0;
13763 const msurface_t **r_surfacelist = NULL;
13764 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
13766 int i, j, endj, flagsmask;
13767 dp_model_t *model = r_refdef.scene.worldmodel;
13768 msurface_t *surfaces;
13769 unsigned char *update;
13770 int numsurfacelist = 0;
13774 if (r_maxsurfacelist < model->num_surfaces)
13776 r_maxsurfacelist = model->num_surfaces;
13778 Mem_Free((msurface_t**)r_surfacelist);
13779 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
13782 RSurf_ActiveWorldEntity();
13784 surfaces = model->data_surfaces;
13785 update = model->brushq1.lightmapupdateflags;
13787 // update light styles on this submodel
13788 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
13790 model_brush_lightstyleinfo_t *style;
13791 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
13793 if (style->value != r_refdef.scene.lightstylevalue[style->style])
13795 int *list = style->surfacelist;
13796 style->value = r_refdef.scene.lightstylevalue[style->style];
13797 for (j = 0;j < style->numsurfaces;j++)
13798 update[list[j]] = true;
13803 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
13807 R_DrawDebugModel();
13808 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13812 rsurface.lightmaptexture = NULL;
13813 rsurface.deluxemaptexture = NULL;
13814 rsurface.uselightmaptexture = false;
13815 rsurface.texture = NULL;
13816 rsurface.rtlight = NULL;
13817 numsurfacelist = 0;
13818 // add visible surfaces to draw list
13819 for (i = 0;i < model->nummodelsurfaces;i++)
13821 j = model->sortedmodelsurfaces[i];
13822 if (r_refdef.viewcache.world_surfacevisible[j])
13823 r_surfacelist[numsurfacelist++] = surfaces + j;
13825 // update lightmaps if needed
13826 if (model->brushq1.firstrender)
13828 model->brushq1.firstrender = false;
13829 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13831 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
13835 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13836 if (r_refdef.viewcache.world_surfacevisible[j])
13838 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
13840 // don't do anything if there were no surfaces
13841 if (!numsurfacelist)
13843 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13846 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
13848 // add to stats if desired
13849 if (r_speeds.integer && !skysurfaces && !depthonly)
13851 r_refdef.stats.world_surfaces += numsurfacelist;
13852 for (j = 0;j < numsurfacelist;j++)
13853 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
13856 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13859 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
13861 int i, j, endj, flagsmask;
13862 dp_model_t *model = ent->model;
13863 msurface_t *surfaces;
13864 unsigned char *update;
13865 int numsurfacelist = 0;
13869 if (r_maxsurfacelist < model->num_surfaces)
13871 r_maxsurfacelist = model->num_surfaces;
13873 Mem_Free((msurface_t **)r_surfacelist);
13874 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
13877 // if the model is static it doesn't matter what value we give for
13878 // wantnormals and wanttangents, so this logic uses only rules applicable
13879 // to a model, knowing that they are meaningless otherwise
13880 if (ent == r_refdef.scene.worldentity)
13881 RSurf_ActiveWorldEntity();
13882 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
13883 RSurf_ActiveModelEntity(ent, false, false, false);
13885 RSurf_ActiveModelEntity(ent, true, true, true);
13886 else if (depthonly)
13888 switch (vid.renderpath)
13890 case RENDERPATH_GL20:
13891 case RENDERPATH_D3D9:
13892 case RENDERPATH_D3D10:
13893 case RENDERPATH_D3D11:
13894 case RENDERPATH_SOFT:
13895 case RENDERPATH_GLES2:
13896 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
13898 case RENDERPATH_GL13:
13899 case RENDERPATH_GL11:
13900 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
13906 switch (vid.renderpath)
13908 case RENDERPATH_GL20:
13909 case RENDERPATH_D3D9:
13910 case RENDERPATH_D3D10:
13911 case RENDERPATH_D3D11:
13912 case RENDERPATH_SOFT:
13913 case RENDERPATH_GLES2:
13914 RSurf_ActiveModelEntity(ent, true, true, false);
13916 case RENDERPATH_GL13:
13917 case RENDERPATH_GL11:
13918 RSurf_ActiveModelEntity(ent, true, false, false);
13923 surfaces = model->data_surfaces;
13924 update = model->brushq1.lightmapupdateflags;
13926 // update light styles
13927 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
13929 model_brush_lightstyleinfo_t *style;
13930 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
13932 if (style->value != r_refdef.scene.lightstylevalue[style->style])
13934 int *list = style->surfacelist;
13935 style->value = r_refdef.scene.lightstylevalue[style->style];
13936 for (j = 0;j < style->numsurfaces;j++)
13937 update[list[j]] = true;
13942 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
13946 R_DrawDebugModel();
13947 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13951 rsurface.lightmaptexture = NULL;
13952 rsurface.deluxemaptexture = NULL;
13953 rsurface.uselightmaptexture = false;
13954 rsurface.texture = NULL;
13955 rsurface.rtlight = NULL;
13956 numsurfacelist = 0;
13957 // add visible surfaces to draw list
13958 for (i = 0;i < model->nummodelsurfaces;i++)
13959 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
13960 // don't do anything if there were no surfaces
13961 if (!numsurfacelist)
13963 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13966 // update lightmaps if needed
13970 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13975 R_BuildLightMap(ent, surfaces + j);
13980 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13982 R_BuildLightMap(ent, surfaces + j);
13983 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
13985 // add to stats if desired
13986 if (r_speeds.integer && !skysurfaces && !depthonly)
13988 r_refdef.stats.entities_surfaces += numsurfacelist;
13989 for (j = 0;j < numsurfacelist;j++)
13990 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
13993 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13996 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
13998 static texture_t texture;
13999 static msurface_t surface;
14000 const msurface_t *surfacelist = &surface;
14002 // fake enough texture and surface state to render this geometry
14004 texture.update_lastrenderframe = -1; // regenerate this texture
14005 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
14006 texture.currentskinframe = skinframe;
14007 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
14008 texture.offsetmapping = OFFSETMAPPING_OFF;
14009 texture.offsetscale = 1;
14010 texture.specularscalemod = 1;
14011 texture.specularpowermod = 1;
14013 surface.texture = &texture;
14014 surface.num_triangles = numtriangles;
14015 surface.num_firsttriangle = firsttriangle;
14016 surface.num_vertices = numvertices;
14017 surface.num_firstvertex = firstvertex;
14020 rsurface.texture = R_GetCurrentTexture(surface.texture);
14021 rsurface.lightmaptexture = NULL;
14022 rsurface.deluxemaptexture = NULL;
14023 rsurface.uselightmaptexture = false;
14024 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14027 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)
14029 static msurface_t surface;
14030 const msurface_t *surfacelist = &surface;
14032 // fake enough texture and surface state to render this geometry
14033 surface.texture = texture;
14034 surface.num_triangles = numtriangles;
14035 surface.num_firsttriangle = firsttriangle;
14036 surface.num_vertices = numvertices;
14037 surface.num_firstvertex = firstvertex;
14040 rsurface.texture = R_GetCurrentTexture(surface.texture);
14041 rsurface.lightmaptexture = NULL;
14042 rsurface.deluxemaptexture = NULL;
14043 rsurface.uselightmaptexture = false;
14044 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);