2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 #include "cl_dyntexture.h"
30 #include "dpsoftrast.h"
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
37 mempool_t *r_main_mempool;
38 rtexturepool_t *r_main_texturepool;
40 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
42 static qboolean r_loadnormalmap;
43 static qboolean r_loadgloss;
45 static qboolean r_loaddds;
46 static qboolean r_savedds;
53 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
55 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
56 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
57 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
58 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
59 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
60 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
62 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
63 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
64 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
65 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
66 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
68 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
69 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
70 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
71 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
72 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
73 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
74 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
75 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
76 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
77 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
78 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
79 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
80 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
81 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
82 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
83 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
84 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
85 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
86 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
87 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
88 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
89 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
90 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
91 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
92 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
93 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
94 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
95 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
97 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
98 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
99 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
101 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
102 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
103 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
104 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
105 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
106 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
107 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
108 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
109 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
110 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
111 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
112 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
113 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
114 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
115 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
116 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
117 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
118 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
119 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
121 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
122 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
123 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
124 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
125 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
126 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
127 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
128 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
130 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
131 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
133 cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
134 cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
135 cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
136 cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
137 cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
139 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
140 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
141 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
143 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
144 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
145 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
146 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
147 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
148 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
149 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
150 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
151 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
152 cvar_t r_glsl_postprocess_uservec1_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec1_enable", "1", "enables postprocessing uservec1 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
153 cvar_t r_glsl_postprocess_uservec2_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec2_enable", "1", "enables postprocessing uservec2 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
154 cvar_t r_glsl_postprocess_uservec3_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec3_enable", "1", "enables postprocessing uservec3 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
155 cvar_t r_glsl_postprocess_uservec4_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec4_enable", "1", "enables postprocessing uservec4 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
157 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
158 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
159 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
160 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
161 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
162 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
164 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
165 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
166 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
167 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
169 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
170 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
171 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
172 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
173 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
174 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
175 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
177 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
178 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
179 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
180 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivalent to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
181 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
182 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
183 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
184 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
185 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
186 cvar_t r_hdr_irisadaptation_fade = {CVAR_SAVE, "r_hdr_irisadaptation_fade", "1", "fade rate at which value adjusts"};
188 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
190 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
192 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
194 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
195 cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
196 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accordingly, 2: Make it a continuous rotation"};
197 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
198 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
199 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "5", "fake perspective effect for SPR_OVERHEAD sprites"};
200 cvar_t r_overheadsprites_pushback = {CVAR_SAVE, "r_overheadsprites_pushback", "15", "how far to pull the SPR_OVERHEAD sprites toward the eye (used to avoid intersections with 3D models)"};
201 cvar_t r_overheadsprites_scalex = {CVAR_SAVE, "r_overheadsprites_scalex", "1", "additional scale for overhead sprites for x axis"};
202 cvar_t r_overheadsprites_scaley = {CVAR_SAVE, "r_overheadsprites_scaley", "1", "additional scale for overhead sprites for y axis"};
204 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
205 cvar_t r_glsl_saturation_redcompensate = {CVAR_SAVE, "r_glsl_saturation_redcompensate", "0", "a 'vampire sight' addition to desaturation effect, does compensation for red color, r_glsl_restart is required"};
207 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "0.5", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
209 extern cvar_t v_glslgamma;
211 extern qboolean v_flipped_state;
213 static struct r_bloomstate_s
218 int bloomwidth, bloomheight;
220 int screentexturewidth, screentextureheight;
221 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
223 int bloomtexturewidth, bloomtextureheight;
224 rtexture_t *texture_bloom;
226 // arrays for rendering the screen passes
227 float screentexcoord2f[8];
228 float bloomtexcoord2f[8];
229 float offsettexcoord2f[8];
231 r_viewport_t viewport;
235 r_waterstate_t r_waterstate;
237 /// shadow volume bsp struct with automatically growing nodes buffer
240 rtexture_t *r_texture_blanknormalmap;
241 rtexture_t *r_texture_white;
242 rtexture_t *r_texture_grey128;
243 rtexture_t *r_texture_black;
244 rtexture_t *r_texture_notexture;
245 rtexture_t *r_texture_whitecube;
246 rtexture_t *r_texture_normalizationcube;
247 rtexture_t *r_texture_fogattenuation;
248 rtexture_t *r_texture_fogheighttexture;
249 rtexture_t *r_texture_gammaramps;
250 unsigned int r_texture_gammaramps_serial;
251 //rtexture_t *r_texture_fogintensity;
252 rtexture_t *r_texture_reflectcube;
254 // TODO: hash lookups?
255 typedef struct cubemapinfo_s
262 int r_texture_numcubemaps;
263 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
265 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
266 unsigned int r_numqueries;
267 unsigned int r_maxqueries;
269 typedef struct r_qwskincache_s
271 char name[MAX_QPATH];
272 skinframe_t *skinframe;
276 static r_qwskincache_t *r_qwskincache;
277 static int r_qwskincache_size;
279 /// vertex coordinates for a quad that covers the screen exactly
280 extern const float r_screenvertex3f[12];
281 extern const float r_d3dscreenvertex3f[12];
282 const float r_screenvertex3f[12] =
289 const float r_d3dscreenvertex3f[12] =
297 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
300 for (i = 0;i < verts;i++)
311 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
314 for (i = 0;i < verts;i++)
324 // FIXME: move this to client?
327 if (gamemode == GAME_NEHAHRA)
329 Cvar_Set("gl_fogenable", "0");
330 Cvar_Set("gl_fogdensity", "0.2");
331 Cvar_Set("gl_fogred", "0.3");
332 Cvar_Set("gl_foggreen", "0.3");
333 Cvar_Set("gl_fogblue", "0.3");
335 r_refdef.fog_density = 0;
336 r_refdef.fog_red = 0;
337 r_refdef.fog_green = 0;
338 r_refdef.fog_blue = 0;
339 r_refdef.fog_alpha = 1;
340 r_refdef.fog_start = 0;
341 r_refdef.fog_end = 16384;
342 r_refdef.fog_height = 1<<30;
343 r_refdef.fog_fadedepth = 128;
344 memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
347 static void R_BuildBlankTextures(void)
349 unsigned char data[4];
350 data[2] = 128; // normal X
351 data[1] = 128; // normal Y
352 data[0] = 255; // normal Z
353 data[3] = 128; // height
354 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
359 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
364 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
369 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
372 static void R_BuildNoTexture(void)
375 unsigned char pix[16][16][4];
376 // this makes a light grey/dark grey checkerboard texture
377 for (y = 0;y < 16;y++)
379 for (x = 0;x < 16;x++)
381 if ((y < 8) ^ (x < 8))
397 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
400 static void R_BuildWhiteCube(void)
402 unsigned char data[6*1*1*4];
403 memset(data, 255, sizeof(data));
404 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
407 static void R_BuildNormalizationCube(void)
411 vec_t s, t, intensity;
414 data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
415 for (side = 0;side < 6;side++)
417 for (y = 0;y < NORMSIZE;y++)
419 for (x = 0;x < NORMSIZE;x++)
421 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
422 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
457 intensity = 127.0f / sqrt(DotProduct(v, v));
458 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
459 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
460 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
461 data[((side*64+y)*64+x)*4+3] = 255;
465 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
469 static void R_BuildFogTexture(void)
473 unsigned char data1[FOGWIDTH][4];
474 //unsigned char data2[FOGWIDTH][4];
477 r_refdef.fogmasktable_start = r_refdef.fog_start;
478 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
479 r_refdef.fogmasktable_range = r_refdef.fogrange;
480 r_refdef.fogmasktable_density = r_refdef.fog_density;
482 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
483 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
485 d = (x * r - r_refdef.fogmasktable_start);
486 if(developer_extra.integer)
487 Con_DPrintf("%f ", d);
489 if (r_fog_exp2.integer)
490 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
492 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
493 if(developer_extra.integer)
494 Con_DPrintf(" : %f ", alpha);
495 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
496 if(developer_extra.integer)
497 Con_DPrintf(" = %f\n", alpha);
498 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
501 for (x = 0;x < FOGWIDTH;x++)
503 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
508 //data2[x][0] = 255 - b;
509 //data2[x][1] = 255 - b;
510 //data2[x][2] = 255 - b;
513 if (r_texture_fogattenuation)
515 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
516 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
520 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
521 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
525 static void R_BuildFogHeightTexture(void)
527 unsigned char *inpixels;
535 strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
536 if (r_refdef.fogheighttexturename[0])
537 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
540 r_refdef.fog_height_tablesize = 0;
541 if (r_texture_fogheighttexture)
542 R_FreeTexture(r_texture_fogheighttexture);
543 r_texture_fogheighttexture = NULL;
544 if (r_refdef.fog_height_table2d)
545 Mem_Free(r_refdef.fog_height_table2d);
546 r_refdef.fog_height_table2d = NULL;
547 if (r_refdef.fog_height_table1d)
548 Mem_Free(r_refdef.fog_height_table1d);
549 r_refdef.fog_height_table1d = NULL;
553 r_refdef.fog_height_tablesize = size;
554 r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
555 r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
556 memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
558 // LordHavoc: now the magic - what is that table2d for? it is a cooked
559 // average fog color table accounting for every fog layer between a point
560 // and the camera. (Note: attenuation is handled separately!)
561 for (y = 0;y < size;y++)
563 for (x = 0;x < size;x++)
569 for (j = x;j <= y;j++)
571 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
577 for (j = x;j >= y;j--)
579 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
584 r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
585 r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
586 r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
587 r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
590 r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
593 //=======================================================================================================================================================
595 static const char *builtinshaderstring =
596 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
597 "// written by Forest 'LordHavoc' Hale\n"
598 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
600 "// GL ES shaders use precision modifiers, standard GL does not\n"
607 "#ifdef VERTEX_SHADER\n"
608 "attribute vec4 Attrib_Position; // vertex\n"
609 "attribute vec4 Attrib_Color; // color\n"
610 "attribute vec4 Attrib_TexCoord0; // material texcoords\n"
611 "attribute vec3 Attrib_TexCoord1; // svector\n"
612 "attribute vec3 Attrib_TexCoord2; // tvector\n"
613 "attribute vec3 Attrib_TexCoord3; // normal\n"
614 "attribute vec4 Attrib_TexCoord4; // lightmap texcoords\n"
616 "varying lowp vec4 VertexColor;\n"
618 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
621 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
622 "#define USELIGHTMAP\n"
624 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
625 "#define USEEYEVECTOR\n"
628 "#ifdef USESHADOWMAP2D\n"
629 "# ifdef GL_EXT_gpu_shader4\n"
630 "# extension GL_EXT_gpu_shader4 : enable\n"
632 "# ifdef GL_ARB_texture_gather\n"
633 "# extension GL_ARB_texture_gather : enable\n"
635 "# ifdef GL_AMD_texture_texture4\n"
636 "# extension GL_AMD_texture_texture4 : enable\n"
641 "//#ifdef USESHADOWSAMPLER\n"
642 "//# extension GL_ARB_shadow : enable\n"
645 "//#ifdef __GLSL_CG_DATA_TYPES\n"
646 "//# define myhalf half\n"
647 "//# define myhalf2 half2\n"
648 "//# define myhalf3 half3\n"
649 "//# define myhalf4 half4\n"
651 "# define myhalf mediump float\n"
652 "# define myhalf2 mediump vec2\n"
653 "# define myhalf3 mediump vec3\n"
654 "# define myhalf4 mediump vec4\n"
657 "#ifdef VERTEX_SHADER\n"
658 "uniform highp mat4 ModelViewProjectionMatrix;\n"
661 "#ifdef MODE_DEPTH_OR_SHADOW\n"
662 "#ifdef VERTEX_SHADER\n"
665 " gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
668 "#else // !MODE_DEPTH_ORSHADOW\n"
673 "#ifdef MODE_SHOWDEPTH\n"
674 "#ifdef VERTEX_SHADER\n"
677 " gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
678 " VertexColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
682 "#ifdef FRAGMENT_SHADER\n"
685 " gl_FragColor = VertexColor;\n"
688 "#else // !MODE_SHOWDEPTH\n"
693 "#ifdef MODE_POSTPROCESS\n"
694 "varying mediump vec2 TexCoord1;\n"
695 "varying mediump vec2 TexCoord2;\n"
697 "#ifdef VERTEX_SHADER\n"
700 " gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
701 " TexCoord1 = Attrib_TexCoord0.xy;\n"
703 " TexCoord2 = Attrib_TexCoord4.xy;\n"
708 "#ifdef FRAGMENT_SHADER\n"
709 "uniform sampler2D Texture_First;\n"
711 "uniform sampler2D Texture_Second;\n"
712 "uniform lowp vec4 BloomColorSubtract;\n"
714 "#ifdef USEGAMMARAMPS\n"
715 "uniform sampler2D Texture_GammaRamps;\n"
717 "#ifdef USESATURATION\n"
718 "uniform lowp float Saturation;\n"
720 "#ifdef USEVIEWTINT\n"
721 "uniform lowp vec4 ViewTintColor;\n"
723 "//uncomment these if you want to use them:\n"
724 "uniform mediump vec4 UserVec1;\n"
725 "uniform mediump vec4 UserVec2;\n"
726 "// uniform mediump vec4 UserVec3;\n"
727 "// uniform mediump vec4 UserVec4;\n"
728 "// uniform highp float ClientTime;\n"
729 "uniform mediump vec2 PixelSize;\n"
732 " gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
734 " gl_FragColor += max(vec4(0,0,0,0), texture2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
736 "#ifdef USEVIEWTINT\n"
737 " gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
740 "#ifdef USEPOSTPROCESSING\n"
741 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
742 "// this code does a blur with the radius specified in the first component of r_glsl_postprocess_uservec1 and blends it using the second component\n"
743 " float sobel = 1.0;\n"
744 " // vec2 ts = textureSize(Texture_First, 0);\n"
745 " // vec2 px = vec2(1/ts.x, 1/ts.y);\n"
746 " vec2 px = PixelSize;\n"
747 " vec3 x1 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
748 " vec3 x2 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, 0.0)).rgb;\n"
749 " vec3 x3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
750 " vec3 x4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
751 " vec3 x5 = texture2D(Texture_First, TexCoord1 + vec2( px.x, 0.0)).rgb;\n"
752 " vec3 x6 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
753 " vec3 y1 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
754 " vec3 y2 = texture2D(Texture_First, TexCoord1 + vec2( 0.0,-px.y)).rgb;\n"
755 " vec3 y3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
756 " vec3 y4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
757 " vec3 y5 = texture2D(Texture_First, TexCoord1 + vec2( 0.0, px.y)).rgb;\n"
758 " vec3 y6 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
759 " float px1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x1);\n"
760 " float px2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), x2);\n"
761 " float px3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x3);\n"
762 " float px4 = 1.0 * dot(vec3(0.3, 0.59, 0.11), x4);\n"
763 " float px5 = 2.0 * dot(vec3(0.3, 0.59, 0.11), x5);\n"
764 " float px6 = 1.0 * dot(vec3(0.3, 0.59, 0.11), x6);\n"
765 " float py1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y1);\n"
766 " float py2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), y2);\n"
767 " float py3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y3);\n"
768 " float py4 = 1.0 * dot(vec3(0.3, 0.59, 0.11), y4);\n"
769 " float py5 = 2.0 * dot(vec3(0.3, 0.59, 0.11), y5);\n"
770 " float py6 = 1.0 * dot(vec3(0.3, 0.59, 0.11), y6);\n"
771 " sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
772 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
773 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
774 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
775 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107, 0.707107)) * UserVec1.y;\n"
776 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990, 0.891007)) * UserVec1.y;\n"
777 " gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
778 " gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + vec3(max(0.0, sobel - UserVec2.z))*UserVec2.y;\n"
781 "#ifdef USESATURATION\n"
782 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
783 " float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
784 " // 'vampire sight' effect, wheres red is compensated\n"
785 " #ifdef SATURATION_REDCOMPENSATE\n"
786 " float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n"
787 " gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
788 " gl_FragColor.r += rboost;\n"
790 " // normal desaturation\n"
791 " //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
792 " gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
796 "#ifdef USEGAMMARAMPS\n"
797 " gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
798 " gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
799 " gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
803 "#else // !MODE_POSTPROCESS\n"
808 "#ifdef MODE_GENERIC\n"
809 "#ifdef USEDIFFUSE\n"
810 "varying mediump vec2 TexCoord1;\n"
812 "#ifdef USESPECULAR\n"
813 "varying mediump vec2 TexCoord2;\n"
815 "#ifdef VERTEX_SHADER\n"
818 " VertexColor = Attrib_Color;\n"
819 "#ifdef USEDIFFUSE\n"
820 " TexCoord1 = Attrib_TexCoord0.xy;\n"
822 "#ifdef USESPECULAR\n"
823 " TexCoord2 = Attrib_TexCoord1.xy;\n"
825 " gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
829 "#ifdef FRAGMENT_SHADER\n"
830 "#ifdef USEDIFFUSE\n"
831 "uniform sampler2D Texture_First;\n"
833 "#ifdef USESPECULAR\n"
834 "uniform sampler2D Texture_Second;\n"
839 "#ifdef USEVIEWTINT\n"
840 " gl_FragColor = VertexColor;\n"
842 " gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
844 "#ifdef USEDIFFUSE\n"
845 " gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
848 "#ifdef USESPECULAR\n"
849 " vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
850 "# ifdef USECOLORMAPPING\n"
851 " gl_FragColor *= tex2;\n"
854 " gl_FragColor += tex2;\n"
856 "# ifdef USEVERTEXTEXTUREBLEND\n"
857 " gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
862 "#else // !MODE_GENERIC\n"
867 "#ifdef MODE_BLOOMBLUR\n"
868 "varying mediump vec2 TexCoord;\n"
869 "#ifdef VERTEX_SHADER\n"
872 " VertexColor = Attrib_Color;\n"
873 " TexCoord = Attrib_TexCoord0.xy;\n"
874 " gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
878 "#ifdef FRAGMENT_SHADER\n"
879 "uniform sampler2D Texture_First;\n"
880 "uniform mediump vec4 BloomBlur_Parameters;\n"
885 " vec2 tc = TexCoord;\n"
886 " vec3 color = texture2D(Texture_First, tc).rgb;\n"
887 " tc += BloomBlur_Parameters.xy;\n"
888 " for (i = 1;i < SAMPLES;i++)\n"
890 " color += texture2D(Texture_First, tc).rgb;\n"
891 " tc += BloomBlur_Parameters.xy;\n"
893 " gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
896 "#else // !MODE_BLOOMBLUR\n"
897 "#ifdef MODE_REFRACTION\n"
898 "varying mediump vec2 TexCoord;\n"
899 "varying highp vec4 ModelViewProjectionPosition;\n"
900 "uniform highp mat4 TexMatrix;\n"
901 "#ifdef VERTEX_SHADER\n"
905 " TexCoord = vec2(TexMatrix * Attrib_TexCoord0);\n"
906 " gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
907 " ModelViewProjectionPosition = gl_Position;\n"
911 "#ifdef FRAGMENT_SHADER\n"
912 "uniform sampler2D Texture_Normal;\n"
913 "uniform sampler2D Texture_Refraction;\n"
914 "uniform sampler2D Texture_Reflection;\n"
916 "uniform mediump vec4 DistortScaleRefractReflect;\n"
917 "uniform mediump vec4 ScreenScaleRefractReflect;\n"
918 "uniform mediump vec4 ScreenCenterRefractReflect;\n"
919 "uniform lowp vec4 RefractColor;\n"
920 "uniform lowp vec4 ReflectColor;\n"
921 "uniform mediump float ReflectFactor;\n"
922 "uniform mediump float ReflectOffset;\n"
926 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
927 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
928 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
929 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
930 " // FIXME temporary hack to detect the case that the reflection\n"
931 " // gets blackened at edges due to leaving the area that contains actual\n"
933 " // Remove this 'ack once we have a better way to stop this thing from\n"
935 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
936 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
937 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
938 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
939 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
940 " gl_FragColor = vec4(texture2D(Texture_Refraction, ScreenTexCoord).rgb, 1.0) * RefractColor;\n"
943 "#else // !MODE_REFRACTION\n"
948 "#ifdef MODE_WATER\n"
949 "varying mediump vec2 TexCoord;\n"
950 "varying highp vec3 EyeVector;\n"
951 "varying highp vec4 ModelViewProjectionPosition;\n"
952 "#ifdef VERTEX_SHADER\n"
953 "uniform highp vec3 EyePosition;\n"
954 "uniform highp mat4 TexMatrix;\n"
958 " TexCoord = vec2(TexMatrix * Attrib_TexCoord0);\n"
959 " vec3 EyeVectorModelSpace = EyePosition - Attrib_Position.xyz;\n"
960 " EyeVector.x = dot(EyeVectorModelSpace, Attrib_TexCoord1.xyz);\n"
961 " EyeVector.y = dot(EyeVectorModelSpace, Attrib_TexCoord2.xyz);\n"
962 " EyeVector.z = dot(EyeVectorModelSpace, Attrib_TexCoord3.xyz);\n"
963 " gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
964 " ModelViewProjectionPosition = gl_Position;\n"
968 "#ifdef FRAGMENT_SHADER\n"
969 "uniform sampler2D Texture_Normal;\n"
970 "uniform sampler2D Texture_Refraction;\n"
971 "uniform sampler2D Texture_Reflection;\n"
973 "uniform mediump vec4 DistortScaleRefractReflect;\n"
974 "uniform mediump vec4 ScreenScaleRefractReflect;\n"
975 "uniform mediump vec4 ScreenCenterRefractReflect;\n"
976 "uniform lowp vec4 RefractColor;\n"
977 "uniform lowp vec4 ReflectColor;\n"
978 "uniform mediump float ReflectFactor;\n"
979 "uniform mediump float ReflectOffset;\n"
980 "uniform highp float ClientTime;\n"
981 "#ifdef USENORMALMAPSCROLLBLEND\n"
982 "uniform highp vec2 NormalmapScrollBlend;\n"
987 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
988 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
989 " vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
990 " //SafeScreenTexCoord = gl_FragCoord.xyxy * vec4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
991 " // slight water animation via 2 layer scrolling (todo: tweak)\n"
992 " #ifdef USENORMALMAPSCROLLBLEND\n"
993 " vec3 normal = texture2D(Texture_Normal, (TexCoord + vec2(0.08, 0.08)*ClientTime*NormalmapScrollBlend.x*0.5)*NormalmapScrollBlend.y).rgb - vec3(1.0);\n"
994 " normal += texture2D(Texture_Normal, (TexCoord + vec2(-0.06, -0.09)*ClientTime*NormalmapScrollBlend.x)*NormalmapScrollBlend.y*0.75).rgb;\n"
995 " vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(normal) + vec3(0.15)).xyxy * DistortScaleRefractReflect;\n"
997 " vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
999 " // FIXME temporary hack to detect the case that the reflection\n"
1000 " // gets blackened at edges due to leaving the area that contains actual\n"
1002 " // Remove this 'ack once we have a better way to stop this thing from\n"
1004 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.005, 0.01)).rgb) / 0.002);\n"
1005 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.005, -0.01)).rgb) / 0.002);\n"
1006 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, 0.01)).rgb) / 0.002);\n"
1007 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, -0.01)).rgb) / 0.002);\n"
1008 " ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
1009 " f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.005, 0.005)).rgb) / 0.002);\n"
1010 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.005, -0.005)).rgb) / 0.002);\n"
1011 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, 0.005)).rgb) / 0.002);\n"
1012 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, -0.005)).rgb) / 0.002);\n"
1013 " ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
1014 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
1015 " gl_FragColor = mix(vec4(texture2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, vec4(texture2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
1018 "#else // !MODE_WATER\n"
1023 "// common definitions between vertex shader and fragment shader:\n"
1025 "varying mediump vec2 TexCoord;\n"
1026 "#ifdef USEVERTEXTEXTUREBLEND\n"
1027 "varying mediump vec2 TexCoord2;\n"
1029 "#ifdef USELIGHTMAP\n"
1030 "varying mediump vec2 TexCoordLightmap;\n"
1033 "#ifdef MODE_LIGHTSOURCE\n"
1034 "varying mediump vec3 CubeVector;\n"
1037 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
1038 "varying mediump vec3 LightVector;\n"
1041 "#ifdef USEEYEVECTOR\n"
1042 "varying highp vec3 EyeVector;\n"
1045 "varying highp vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
1048 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
1049 "varying lowp vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
1050 "varying lowp vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
1051 "varying lowp vec3 VectorR; // direction of R texcoord (surface normal)\n"
1054 "#ifdef USEREFLECTION\n"
1055 "varying highp vec4 ModelViewProjectionPosition;\n"
1057 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1058 "uniform highp vec3 LightPosition;\n"
1059 "varying highp vec4 ModelViewPosition;\n"
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"
1079 "// 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"
1081 "// fragment shader specific:\n"
1082 "#ifdef FRAGMENT_SHADER\n"
1084 "uniform sampler2D Texture_Normal;\n"
1085 "uniform sampler2D Texture_Color;\n"
1086 "uniform sampler2D Texture_Gloss;\n"
1088 "uniform sampler2D Texture_Glow;\n"
1090 "#ifdef USEVERTEXTEXTUREBLEND\n"
1091 "uniform sampler2D Texture_SecondaryNormal;\n"
1092 "uniform sampler2D Texture_SecondaryColor;\n"
1093 "uniform sampler2D Texture_SecondaryGloss;\n"
1095 "uniform sampler2D Texture_SecondaryGlow;\n"
1098 "#ifdef USECOLORMAPPING\n"
1099 "uniform sampler2D Texture_Pants;\n"
1100 "uniform sampler2D Texture_Shirt;\n"
1103 "#ifdef USEFOGHEIGHTTEXTURE\n"
1104 "uniform sampler2D Texture_FogHeightTexture;\n"
1106 "uniform sampler2D Texture_FogMask;\n"
1108 "#ifdef USELIGHTMAP\n"
1109 "uniform sampler2D Texture_Lightmap;\n"
1111 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1112 "uniform sampler2D Texture_Deluxemap;\n"
1114 "#ifdef USEREFLECTION\n"
1115 "uniform sampler2D Texture_Reflection;\n"
1118 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1119 "uniform sampler2D Texture_ScreenDepth;\n"
1120 "uniform sampler2D Texture_ScreenNormalMap;\n"
1122 "#ifdef USEDEFERREDLIGHTMAP\n"
1123 "uniform sampler2D Texture_ScreenDiffuse;\n"
1124 "uniform sampler2D Texture_ScreenSpecular;\n"
1127 "uniform lowp vec3 Color_Pants;\n"
1128 "uniform lowp vec3 Color_Shirt;\n"
1129 "uniform lowp vec3 FogColor;\n"
1132 "uniform highp float FogRangeRecip;\n"
1133 "uniform highp float FogPlaneViewDist;\n"
1134 "uniform highp float FogHeightFade;\n"
1135 "vec3 FogVertex(vec3 surfacecolor)\n"
1137 " vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
1138 " float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
1140 "#ifdef USEFOGHEIGHTTEXTURE\n"
1141 " vec4 fogheightpixel = texture2D(Texture_FogHeightTexture, vec2(1,1) + vec2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
1142 " fogfrac = fogheightpixel.a;\n"
1143 " return mix(fogheightpixel.rgb * FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1145 "# ifdef USEFOGOUTSIDE\n"
1146 " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1148 " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1150 " return mix(FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1155 "#ifdef USEOFFSETMAPPING\n"
1156 "uniform mediump float OffsetMapping_Scale;\n"
1157 "vec2 OffsetMapping(vec2 TexCoord)\n"
1159 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
1160 " // 14 sample relief mapping: linear search and then binary search\n"
1161 " // this basically steps forward a small amount repeatedly until it finds\n"
1162 " // itself inside solid, then jitters forward and back using decreasing\n"
1163 " // amounts to find the impact\n"
1164 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
1165 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1166 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1167 " vec3 RT = vec3(TexCoord, 1);\n"
1168 " OffsetVector *= 0.1;\n"
1169 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1170 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1171 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1172 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1173 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\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) - 0.5);\n"
1179 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
1180 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
1181 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
1182 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1185 " // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1186 " // this basically moves forward the full distance, and then backs up based\n"
1187 " // on height of samples\n"
1188 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1189 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1190 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1191 " TexCoord += OffsetVector;\n"
1192 " OffsetVector *= 0.5;\n"
1193 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1194 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1195 " return TexCoord;\n"
1198 "#endif // USEOFFSETMAPPING\n"
1200 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1201 "uniform sampler2D Texture_Attenuation;\n"
1202 "uniform samplerCube Texture_Cube;\n"
1205 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
1207 "#ifdef USESHADOWMAP2D\n"
1208 "# ifdef USESHADOWSAMPLER\n"
1209 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1211 "uniform sampler2D Texture_ShadowMap2D;\n"
1215 "#ifdef USESHADOWMAPVSDCT\n"
1216 "uniform samplerCube Texture_CubeProjection;\n"
1219 "#if defined(USESHADOWMAP2D)\n"
1220 "uniform mediump vec2 ShadowMap_TextureScale;\n"
1221 "uniform mediump vec4 ShadowMap_Parameters;\n"
1224 "#if defined(USESHADOWMAP2D)\n"
1225 "# ifdef USESHADOWMAPORTHO\n"
1226 "# define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n"
1228 "# ifdef USESHADOWMAPVSDCT\n"
1229 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1231 " vec3 adir = abs(dir);\n"
1232 " vec2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
1233 " vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1234 " return vec3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1237 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1239 " vec3 adir = abs(dir);\n"
1240 " float ma = adir.z;\n"
1241 " vec4 proj = vec4(dir, 2.5);\n"
1242 " if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
1243 " if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
1244 " vec2 aparams = ShadowMap_Parameters.xy / ma;\n"
1245 " 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"
1249 "#endif // defined(USESHADOWMAP2D)\n"
1251 "# ifdef USESHADOWMAP2D\n"
1252 "float ShadowMapCompare(vec3 dir)\n"
1254 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1257 "# ifdef USESHADOWSAMPLER\n"
1258 "# ifdef USESHADOWMAPPCF\n"
1259 "# define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r \n"
1260 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1261 " 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"
1263 " f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1266 "# ifdef USESHADOWMAPPCF\n"
1267 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1268 "# ifdef GL_ARB_texture_gather\n"
1269 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1271 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1273 " vec2 offset = fract(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
1274 "# if USESHADOWMAPPCF > 1\n"
1275 " vec4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
1276 " vec4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
1277 " vec4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
1278 " vec4 group4 = step(shadowmaptc.z, texval(-2.0, 0.0));\n"
1279 " vec4 group5 = step(shadowmaptc.z, texval( 0.0, 0.0));\n"
1280 " vec4 group6 = step(shadowmaptc.z, texval( 2.0, 0.0));\n"
1281 " vec4 group7 = step(shadowmaptc.z, texval(-2.0, 2.0));\n"
1282 " vec4 group8 = step(shadowmaptc.z, texval( 0.0, 2.0));\n"
1283 " vec4 group9 = step(shadowmaptc.z, texval( 2.0, 2.0));\n"
1284 " vec4 locols = vec4(group1.ab, group3.ab);\n"
1285 " vec4 hicols = vec4(group7.rg, group9.rg);\n"
1286 " locols.yz += group2.ab;\n"
1287 " hicols.yz += group8.rg;\n"
1288 " vec4 midcols = vec4(group1.rg, group3.rg) + vec4(group7.ab, group9.ab) +\n"
1289 " vec4(group4.rg, group6.rg) + vec4(group4.ab, group6.ab) +\n"
1290 " mix(locols, hicols, offset.y);\n"
1291 " vec4 cols = group5 + vec4(group2.rg, group8.ab);\n"
1292 " cols.xyz += mix(midcols.xyz, midcols.yzw, offset.x);\n"
1293 " f = dot(cols, vec4(1.0/25.0));\n"
1295 " vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1296 " vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1297 " vec4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
1298 " vec4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
1299 " vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1300 " mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1301 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1304 "# ifdef GL_EXT_gpu_shader4\n"
1305 "# define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1307 "# define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r \n"
1309 "# if USESHADOWMAPPCF > 1\n"
1310 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1311 " center *= ShadowMap_TextureScale;\n"
1312 " 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"
1313 " 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"
1314 " 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"
1315 " 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"
1316 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1317 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1319 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1320 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1321 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1322 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1323 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1324 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1328 " f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1331 "# ifdef USESHADOWMAPORTHO\n"
1332 " return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1338 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
1339 "#endif // FRAGMENT_SHADER\n"
1344 "#ifdef MODE_DEFERREDGEOMETRY\n"
1345 "#ifdef VERTEX_SHADER\n"
1346 "uniform highp mat4 TexMatrix;\n"
1347 "#ifdef USEVERTEXTEXTUREBLEND\n"
1348 "uniform highp mat4 BackgroundTexMatrix;\n"
1350 "uniform highp mat4 ModelViewMatrix;\n"
1353 " TexCoord = vec2(TexMatrix * Attrib_TexCoord0);\n"
1354 "#ifdef USEVERTEXTEXTUREBLEND\n"
1355 " VertexColor = Attrib_Color;\n"
1356 " TexCoord2 = vec2(BackgroundTexMatrix * Attrib_TexCoord0);\n"
1359 " // transform unnormalized eye direction into tangent space\n"
1360 "#ifdef USEOFFSETMAPPING\n"
1361 " vec3 EyeVectorModelSpace = EyePosition - Attrib_Position.xyz;\n"
1362 " EyeVector.x = dot(EyeVectorModelSpace, Attrib_TexCoord1.xyz);\n"
1363 " EyeVector.y = dot(EyeVectorModelSpace, Attrib_TexCoord2.xyz);\n"
1364 " EyeVector.z = dot(EyeVectorModelSpace, Attrib_TexCoord3.xyz);\n"
1367 " VectorS = (ModelViewMatrix * vec4(Attrib_TexCoord1.xyz, 0)).xyz;\n"
1368 " VectorT = (ModelViewMatrix * vec4(Attrib_TexCoord2.xyz, 0)).xyz;\n"
1369 " VectorR = (ModelViewMatrix * vec4(Attrib_TexCoord3.xyz, 0)).xyz;\n"
1370 " gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
1372 "#endif // VERTEX_SHADER\n"
1374 "#ifdef FRAGMENT_SHADER\n"
1377 "#ifdef USEOFFSETMAPPING\n"
1378 " // apply offsetmapping\n"
1379 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1380 "#define TexCoord TexCoordOffset\n"
1383 "#ifdef USEALPHAKILL\n"
1384 " if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1388 "#ifdef USEVERTEXTEXTUREBLEND\n"
1389 " float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1390 " float terrainblend = clamp(float(VertexColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1391 " //float terrainblend = min(float(VertexColor.a) * alpha * 2.0, float(1.0));\n"
1392 " //float terrainblend = float(VertexColor.a) * alpha > 0.5;\n"
1395 "#ifdef USEVERTEXTEXTUREBLEND\n"
1396 " vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1397 " float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
1399 " vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1400 " float a = texture2D(Texture_Gloss, TexCoord).a;\n"
1403 " gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
1405 "#endif // FRAGMENT_SHADER\n"
1406 "#else // !MODE_DEFERREDGEOMETRY\n"
1411 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1412 "#ifdef VERTEX_SHADER\n"
1413 "uniform highp mat4 ModelViewMatrix;\n"
1416 " ModelViewPosition = ModelViewMatrix * Attrib_Position;\n"
1417 " gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
1419 "#endif // VERTEX_SHADER\n"
1421 "#ifdef FRAGMENT_SHADER\n"
1422 "uniform highp mat4 ViewToLight;\n"
1423 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1424 "uniform highp vec2 ScreenToDepth;\n"
1425 "uniform myhalf3 DeferredColor_Ambient;\n"
1426 "uniform myhalf3 DeferredColor_Diffuse;\n"
1427 "#ifdef USESPECULAR\n"
1428 "uniform myhalf3 DeferredColor_Specular;\n"
1429 "uniform myhalf SpecularPower;\n"
1431 "uniform myhalf2 PixelToScreenTexCoord;\n"
1434 " // calculate viewspace pixel position\n"
1435 " vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1437 " position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1438 " position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1439 " // decode viewspace pixel normal\n"
1440 " myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1441 " myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1442 " // surfacenormal = pixel normal in viewspace\n"
1443 " // LightVector = pixel to light in viewspace\n"
1444 " // CubeVector = position in lightspace\n"
1445 " // eyevector = pixel to view in viewspace\n"
1446 " vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1447 " myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1448 "#ifdef USEDIFFUSE\n"
1449 " // calculate diffuse shading\n"
1450 " myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1451 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1453 "#ifdef USESPECULAR\n"
1454 " // calculate directional shading\n"
1455 " vec3 eyevector = position * -1.0;\n"
1456 "# ifdef USEEXACTSPECULARMATH\n"
1457 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
1459 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1460 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
1464 "#if defined(USESHADOWMAP2D)\n"
1465 " fade *= ShadowMapCompare(CubeVector);\n"
1468 "#ifdef USEDIFFUSE\n"
1469 " gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1471 " gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1473 "#ifdef USESPECULAR\n"
1474 " gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1476 " gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1479 "# ifdef USECUBEFILTER\n"
1480 " vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1481 " gl_FragData[0].rgb *= cubecolor;\n"
1482 " gl_FragData[1].rgb *= cubecolor;\n"
1485 "#endif // FRAGMENT_SHADER\n"
1486 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1491 "#ifdef VERTEX_SHADER\n"
1492 "uniform highp mat4 TexMatrix;\n"
1493 "#ifdef USEVERTEXTEXTUREBLEND\n"
1494 "uniform highp mat4 BackgroundTexMatrix;\n"
1496 "#ifdef MODE_LIGHTSOURCE\n"
1497 "uniform highp mat4 ModelToLight;\n"
1499 "#ifdef USESHADOWMAPORTHO\n"
1500 "uniform highp mat4 ShadowMapMatrix;\n"
1504 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1505 " VertexColor = Attrib_Color;\n"
1507 " // copy the surface texcoord\n"
1508 " TexCoord = vec2(TexMatrix * Attrib_TexCoord0);\n"
1509 "#ifdef USEVERTEXTEXTUREBLEND\n"
1510 " TexCoord2 = vec2(BackgroundTexMatrix * Attrib_TexCoord0);\n"
1512 "#ifdef USELIGHTMAP\n"
1513 " TexCoordLightmap = vec2(Attrib_TexCoord4);\n"
1516 "#ifdef MODE_LIGHTSOURCE\n"
1517 " // transform vertex position into light attenuation/cubemap space\n"
1518 " // (-1 to +1 across the light box)\n"
1519 " CubeVector = vec3(ModelToLight * Attrib_Position);\n"
1521 "# ifdef USEDIFFUSE\n"
1522 " // transform unnormalized light direction into tangent space\n"
1523 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
1524 " // normalize it per pixel)\n"
1525 " vec3 lightminusvertex = LightPosition - Attrib_Position.xyz;\n"
1526 " LightVector.x = dot(lightminusvertex, Attrib_TexCoord1.xyz);\n"
1527 " LightVector.y = dot(lightminusvertex, Attrib_TexCoord2.xyz);\n"
1528 " LightVector.z = dot(lightminusvertex, Attrib_TexCoord3.xyz);\n"
1532 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1533 " LightVector.x = dot(LightDir, Attrib_TexCoord1.xyz);\n"
1534 " LightVector.y = dot(LightDir, Attrib_TexCoord2.xyz);\n"
1535 " LightVector.z = dot(LightDir, Attrib_TexCoord3.xyz);\n"
1538 " // transform unnormalized eye direction into tangent space\n"
1539 "#ifdef USEEYEVECTOR\n"
1540 " vec3 EyeVectorModelSpace = EyePosition - Attrib_Position.xyz;\n"
1541 " EyeVector.x = dot(EyeVectorModelSpace, Attrib_TexCoord1.xyz);\n"
1542 " EyeVector.y = dot(EyeVectorModelSpace, Attrib_TexCoord2.xyz);\n"
1543 " EyeVector.z = dot(EyeVectorModelSpace, Attrib_TexCoord3.xyz);\n"
1547 " EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - Attrib_Position.xyz;\n"
1548 " EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, Attrib_Position);\n"
1551 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
1552 " VectorS = Attrib_TexCoord1.xyz;\n"
1553 " VectorT = Attrib_TexCoord2.xyz;\n"
1554 " VectorR = Attrib_TexCoord3.xyz;\n"
1557 " // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1558 " gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
1560 "#ifdef USESHADOWMAPORTHO\n"
1561 " ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
1564 "#ifdef USEREFLECTION\n"
1565 " ModelViewProjectionPosition = gl_Position;\n"
1568 "#endif // VERTEX_SHADER\n"
1573 "#ifdef FRAGMENT_SHADER\n"
1574 "#ifdef USEDEFERREDLIGHTMAP\n"
1575 "uniform myhalf2 PixelToScreenTexCoord;\n"
1576 "uniform myhalf3 DeferredMod_Diffuse;\n"
1577 "uniform myhalf3 DeferredMod_Specular;\n"
1579 "uniform myhalf3 Color_Ambient;\n"
1580 "uniform myhalf3 Color_Diffuse;\n"
1581 "uniform myhalf3 Color_Specular;\n"
1582 "uniform myhalf SpecularPower;\n"
1584 "uniform myhalf3 Color_Glow;\n"
1586 "uniform myhalf Alpha;\n"
1587 "#ifdef USEREFLECTION\n"
1588 "uniform mediump vec4 DistortScaleRefractReflect;\n"
1589 "uniform mediump vec4 ScreenScaleRefractReflect;\n"
1590 "uniform mediump vec4 ScreenCenterRefractReflect;\n"
1591 "uniform lowp vec4 ReflectColor;\n"
1593 "#ifdef USEREFLECTCUBE\n"
1594 "uniform highp mat4 ModelToReflectCube;\n"
1595 "uniform sampler2D Texture_ReflectMask;\n"
1596 "uniform samplerCube Texture_ReflectCube;\n"
1598 "#ifdef MODE_LIGHTDIRECTION\n"
1599 "uniform myhalf3 LightColor;\n"
1601 "#ifdef MODE_LIGHTSOURCE\n"
1602 "uniform myhalf3 LightColor;\n"
1606 "#ifdef USEOFFSETMAPPING\n"
1607 " // apply offsetmapping\n"
1608 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1609 "#define TexCoord TexCoordOffset\n"
1612 " // combine the diffuse textures (base, pants, shirt)\n"
1613 " myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1614 "#ifdef USEALPHAKILL\n"
1615 " if (color.a < 0.5)\n"
1618 " color.a *= Alpha;\n"
1619 "#ifdef USECOLORMAPPING\n"
1620 " color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1622 "#ifdef USEVERTEXTEXTUREBLEND\n"
1623 " myhalf terrainblend = clamp(myhalf(VertexColor.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1624 " //myhalf terrainblend = min(myhalf(VertexColor.a) * color.a * 2.0, myhalf(1.0));\n"
1625 " //myhalf terrainblend = myhalf(VertexColor.a) * color.a > 0.5;\n"
1626 " color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1628 " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1631 " // get the surface normal\n"
1632 "#ifdef USEVERTEXTEXTUREBLEND\n"
1633 " myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1635 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1638 " // get the material colors\n"
1639 " myhalf3 diffusetex = color.rgb;\n"
1640 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1641 "# ifdef USEVERTEXTEXTUREBLEND\n"
1642 " myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1644 " myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
1648 "#ifdef USEREFLECTCUBE\n"
1649 " vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
1650 " vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
1651 " vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
1652 " diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
1658 "#ifdef MODE_LIGHTSOURCE\n"
1659 " // light source\n"
1660 "#ifdef USEDIFFUSE\n"
1661 " myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1662 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1663 " color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1664 "#ifdef USESPECULAR\n"
1665 "#ifdef USEEXACTSPECULARMATH\n"
1666 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1668 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1669 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1671 " color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
1674 " color.rgb = diffusetex * Color_Ambient;\n"
1676 " color.rgb *= LightColor;\n"
1677 " color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1678 "#if defined(USESHADOWMAP2D)\n"
1679 " color.rgb *= ShadowMapCompare(CubeVector);\n"
1681 "# ifdef USECUBEFILTER\n"
1682 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1684 "#endif // MODE_LIGHTSOURCE\n"
1689 "#ifdef MODE_LIGHTDIRECTION\n"
1691 "#ifdef USEDIFFUSE\n"
1692 " myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1694 "#define lightcolor LightColor\n"
1695 "#endif // MODE_LIGHTDIRECTION\n"
1696 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1698 " // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1699 " myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1700 " myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1701 " // convert modelspace light vector to tangentspace\n"
1702 " myhalf3 lightnormal;\n"
1703 " lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1704 " lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1705 " lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1706 " lightnormal = normalize(lightnormal); // VectorS/T/R are not always perfectly normalized, and EXACTSPECULARMATH is very picky about this\n"
1707 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1708 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1709 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1710 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1711 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1712 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1713 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1714 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1715 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1716 " lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1717 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1718 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1720 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1721 " myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1722 " myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1728 "#ifdef MODE_FAKELIGHT\n"
1730 "myhalf3 lightnormal = myhalf3(normalize(EyeVector));\n"
1731 "myhalf3 lightcolor = myhalf3(1.0);\n"
1732 "#endif // MODE_FAKELIGHT\n"
1737 "#ifdef MODE_LIGHTMAP\n"
1738 " color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1739 "#endif // MODE_LIGHTMAP\n"
1740 "#ifdef MODE_VERTEXCOLOR\n"
1741 " color.rgb = diffusetex * (Color_Ambient + myhalf3(VertexColor.rgb) * Color_Diffuse);\n"
1742 "#endif // MODE_VERTEXCOLOR\n"
1743 "#ifdef MODE_FLATCOLOR\n"
1744 " color.rgb = diffusetex * Color_Ambient;\n"
1745 "#endif // MODE_FLATCOLOR\n"
1751 "# ifdef USEDIFFUSE\n"
1752 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1753 "# ifdef USESPECULAR\n"
1754 "# ifdef USEEXACTSPECULARMATH\n"
1755 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1757 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1758 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1760 " color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
1762 " color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1765 " color.rgb = diffusetex * Color_Ambient;\n"
1769 "#ifdef USESHADOWMAPORTHO\n"
1770 " color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
1773 "#ifdef USEDEFERREDLIGHTMAP\n"
1774 " vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1775 " color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1776 " color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1780 "#ifdef USEVERTEXTEXTUREBLEND\n"
1781 " color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1783 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1788 " color.rgb = FogVertex(color.rgb);\n"
1791 " // 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"
1792 "#ifdef USEREFLECTION\n"
1793 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1794 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1795 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1796 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1797 " // FIXME temporary hack to detect the case that the reflection\n"
1798 " // gets blackened at edges due to leaving the area that contains actual\n"
1800 " // Remove this 'ack once we have a better way to stop this thing from\n"
1802 " float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1803 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1804 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1805 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1806 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1807 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1810 " gl_FragColor = vec4(color);\n"
1812 "#endif // FRAGMENT_SHADER\n"
1814 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1815 "#endif // !MODE_DEFERREDGEOMETRY\n"
1816 "#endif // !MODE_WATER\n"
1817 "#endif // !MODE_REFRACTION\n"
1818 "#endif // !MODE_BLOOMBLUR\n"
1819 "#endif // !MODE_GENERIC\n"
1820 "#endif // !MODE_POSTPROCESS\n"
1821 "#endif // !MODE_SHOWDEPTH\n"
1822 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1826 =========================================================================================================================================================
1830 =========================================================================================================================================================
1834 =========================================================================================================================================================
1838 =========================================================================================================================================================
1842 =========================================================================================================================================================
1846 =========================================================================================================================================================
1850 =========================================================================================================================================================
1853 const char *builtinhlslshaderstring =
1854 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1855 "// written by Forest 'LordHavoc' Hale\n"
1856 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1858 "// FIXME: we need to get rid of ModelViewProjectionPosition to make room for the texcoord for this\n"
1859 "#if defined(USEREFLECTION)\n"
1860 "#undef USESHADOWMAPORTHO\n"
1863 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
1866 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1867 "#define USELIGHTMAP\n"
1869 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
1870 "#define USEEYEVECTOR\n"
1873 "#ifdef FRAGMENT_SHADER\n"
1875 "//#undef USESHADOWMAPPCF\n"
1876 "//#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1877 "#define texDepth2D(tex,texcoord) dot(tex2D(tex,texcoord).rgb, float3(1.0, 255.0/65536.0, 255.0/16777216.0))\n"
1879 "#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1883 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1884 "#ifdef VERTEX_SHADER\n"
1887 "float4 gl_Vertex : POSITION,\n"
1888 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1889 "out float4 gl_Position : POSITION,\n"
1890 "out float Depth : TEXCOORD0\n"
1893 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1894 " Depth = gl_Position.z;\n"
1898 "#ifdef FRAGMENT_SHADER\n"
1901 "float Depth : TEXCOORD0,\n"
1902 "out float4 gl_FragColor : COLOR\n"
1905 "// float4 temp = float4(Depth,Depth*(65536.0/255.0),Depth*(16777216.0/255.0),0.0);\n"
1906 " float4 temp = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
1907 " temp.yz -= floor(temp.yz);\n"
1908 " gl_FragColor = temp;\n"
1909 "// gl_FragColor = float4(Depth,0,0,0);\n"
1912 "#else // !MODE_DEPTH_ORSHADOW\n"
1917 "#ifdef MODE_SHOWDEPTH\n"
1918 "#ifdef VERTEX_SHADER\n"
1921 "float4 gl_Vertex : POSITION,\n"
1922 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1923 "out float4 gl_Position : POSITION,\n"
1924 "out float4 gl_FrontColor : COLOR0\n"
1927 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1928 " gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1932 "#ifdef FRAGMENT_SHADER\n"
1935 "float4 gl_FrontColor : COLOR0,\n"
1936 "out float4 gl_FragColor : COLOR\n"
1939 " gl_FragColor = gl_FrontColor;\n"
1942 "#else // !MODE_SHOWDEPTH\n"
1947 "#ifdef MODE_POSTPROCESS\n"
1949 "#ifdef VERTEX_SHADER\n"
1952 "float4 gl_Vertex : POSITION,\n"
1953 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1954 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1955 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
1956 "out float4 gl_Position : POSITION,\n"
1957 "out float2 TexCoord1 : TEXCOORD0,\n"
1958 "out float2 TexCoord2 : TEXCOORD1\n"
1961 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1962 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
1964 " TexCoord2 = gl_MultiTexCoord4.xy;\n"
1969 "#ifdef FRAGMENT_SHADER\n"
1972 "float2 TexCoord1 : TEXCOORD0,\n"
1973 "float2 TexCoord2 : TEXCOORD1,\n"
1974 "uniform sampler Texture_First : register(s0),\n"
1976 "uniform sampler Texture_Second : register(s1),\n"
1978 "#ifdef USEGAMMARAMPS\n"
1979 "uniform sampler Texture_GammaRamps : register(s2),\n"
1981 "#ifdef USESATURATION\n"
1982 "uniform float Saturation : register(c30),\n"
1984 "#ifdef USEVIEWTINT\n"
1985 "uniform float4 ViewTintColor : register(c41),\n"
1987 "uniform float4 UserVec1 : register(c37),\n"
1988 "uniform float4 UserVec2 : register(c38),\n"
1989 "uniform float4 UserVec3 : register(c39),\n"
1990 "uniform float4 UserVec4 : register(c40),\n"
1991 "uniform float ClientTime : register(c2),\n"
1992 "uniform float2 PixelSize : register(c25),\n"
1993 "uniform float4 BloomColorSubtract : register(c43),\n"
1994 "out float4 gl_FragColor : COLOR\n"
1997 " gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
1999 " gl_FragColor += max(float4(0,0,0,0), tex2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
2001 "#ifdef USEVIEWTINT\n"
2002 " gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
2005 "#ifdef USEPOSTPROCESSING\n"
2006 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
2007 "// 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"
2008 " float sobel = 1.0;\n"
2009 " // float2 ts = textureSize(Texture_First, 0);\n"
2010 " // float2 px = float2(1/ts.x, 1/ts.y);\n"
2011 " float2 px = PixelSize;\n"
2012 " float3 x1 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
2013 " float3 x2 = tex2D(Texture_First, TexCoord1 + float2(-px.x, 0.0)).rgb;\n"
2014 " float3 x3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
2015 " float3 x4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
2016 " float3 x5 = tex2D(Texture_First, TexCoord1 + float2( px.x, 0.0)).rgb;\n"
2017 " float3 x6 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
2018 " float3 y1 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
2019 " float3 y2 = tex2D(Texture_First, TexCoord1 + float2( 0.0,-px.y)).rgb;\n"
2020 " float3 y3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
2021 " float3 y4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
2022 " float3 y5 = tex2D(Texture_First, TexCoord1 + float2( 0.0, px.y)).rgb;\n"
2023 " float3 y6 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
2024 " float px1 = -1.0 * dot(float3(0.3, 0.59, 0.11), x1);\n"
2025 " float px2 = -2.0 * dot(float3(0.3, 0.59, 0.11), x2);\n"
2026 " float px3 = -1.0 * dot(float3(0.3, 0.59, 0.11), x3);\n"
2027 " float px4 = 1.0 * dot(float3(0.3, 0.59, 0.11), x4);\n"
2028 " float px5 = 2.0 * dot(float3(0.3, 0.59, 0.11), x5);\n"
2029 " float px6 = 1.0 * dot(float3(0.3, 0.59, 0.11), x6);\n"
2030 " float py1 = -1.0 * dot(float3(0.3, 0.59, 0.11), y1);\n"
2031 " float py2 = -2.0 * dot(float3(0.3, 0.59, 0.11), y2);\n"
2032 " float py3 = -1.0 * dot(float3(0.3, 0.59, 0.11), y3);\n"
2033 " float py4 = 1.0 * dot(float3(0.3, 0.59, 0.11), y4);\n"
2034 " float py5 = 2.0 * dot(float3(0.3, 0.59, 0.11), y5);\n"
2035 " float py6 = 1.0 * dot(float3(0.3, 0.59, 0.11), y6);\n"
2036 " sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
2037 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
2038 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
2039 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
2040 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107, 0.707107)) * UserVec1.y;\n"
2041 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990, 0.891007)) * UserVec1.y;\n"
2042 " gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
2043 " gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + float3(1,1,1)*max(0.0, sobel - UserVec2.z)*UserVec2.y;\n"
2046 "#ifdef USESATURATION\n"
2047 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
2048 " float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
2049 " // 'vampire sight' effect, wheres red is compensated\n"
2050 " #ifdef SATURATION_REDCOMPENSATE\n"
2051 " float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n"
2052 " gl_FragColor.rgb = lerp(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2053 " gl_FragColor.r += r;\n"
2055 " // normal desaturation\n"
2056 " //gl_FragColor = float3(y,y,y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
2057 " gl_FragColor.rgb = lerp(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2061 "#ifdef USEGAMMARAMPS\n"
2062 " gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
2063 " gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
2064 " gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
2068 "#else // !MODE_POSTPROCESS\n"
2073 "#ifdef MODE_GENERIC\n"
2074 "#ifdef VERTEX_SHADER\n"
2077 "float4 gl_Vertex : POSITION,\n"
2078 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2079 "float4 gl_Color : COLOR0,\n"
2080 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2081 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2082 "out float4 gl_Position : POSITION,\n"
2083 "#ifdef USEDIFFUSE\n"
2084 "out float2 TexCoord1 : TEXCOORD0,\n"
2086 "#ifdef USESPECULAR\n"
2087 "out float2 TexCoord2 : TEXCOORD1,\n"
2089 "out float4 gl_FrontColor : COLOR\n"
2093 " gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2095 " gl_FrontColor = gl_Color; // Cg is forward\n"
2097 "#ifdef USEDIFFUSE\n"
2098 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
2100 "#ifdef USESPECULAR\n"
2101 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
2103 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2107 "#ifdef FRAGMENT_SHADER\n"
2111 "float4 gl_FrontColor : COLOR0,\n"
2112 "float2 TexCoord1 : TEXCOORD0,\n"
2113 "float2 TexCoord2 : TEXCOORD1,\n"
2114 "#ifdef USEDIFFUSE\n"
2115 "uniform sampler Texture_First : register(s0),\n"
2117 "#ifdef USESPECULAR\n"
2118 "uniform sampler Texture_Second : register(s1),\n"
2120 "out float4 gl_FragColor : COLOR\n"
2123 "#ifdef USEVIEWTINT\n"
2124 " gl_FragColor = gl_FrontColor;\n"
2126 " gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
2128 "#ifdef USEDIFFUSE\n"
2129 " gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
2132 "#ifdef USESPECULAR\n"
2133 " float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
2134 "# ifdef USECOLORMAPPING\n"
2135 " gl_FragColor *= tex2;\n"
2138 " gl_FragColor += tex2;\n"
2140 "# ifdef USEVERTEXTEXTUREBLEND\n"
2141 " gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
2146 "#else // !MODE_GENERIC\n"
2151 "#ifdef MODE_BLOOMBLUR\n"
2152 "#ifdef VERTEX_SHADER\n"
2155 "float4 gl_Vertex : POSITION,\n"
2156 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2157 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2158 "out float4 gl_Position : POSITION,\n"
2159 "out float2 TexCoord : TEXCOORD0\n"
2162 " TexCoord = gl_MultiTexCoord0.xy;\n"
2163 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2167 "#ifdef FRAGMENT_SHADER\n"
2171 "float2 TexCoord : TEXCOORD0,\n"
2172 "uniform sampler Texture_First : register(s0),\n"
2173 "uniform float4 BloomBlur_Parameters : register(c1),\n"
2174 "out float4 gl_FragColor : COLOR\n"
2178 " float2 tc = TexCoord;\n"
2179 " float3 color = tex2D(Texture_First, tc).rgb;\n"
2180 " tc += BloomBlur_Parameters.xy;\n"
2181 " for (i = 1;i < SAMPLES;i++)\n"
2183 " color += tex2D(Texture_First, tc).rgb;\n"
2184 " tc += BloomBlur_Parameters.xy;\n"
2186 " gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
2189 "#else // !MODE_BLOOMBLUR\n"
2190 "#ifdef MODE_REFRACTION\n"
2191 "#ifdef VERTEX_SHADER\n"
2194 "float4 gl_Vertex : POSITION,\n"
2195 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2196 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2197 "uniform float4x4 TexMatrix : register(c0),\n"
2198 "uniform float3 EyePosition : register(c24),\n"
2199 "out float4 gl_Position : POSITION,\n"
2200 "out float2 TexCoord : TEXCOORD0,\n"
2201 "out float3 EyeVector : TEXCOORD1,\n"
2202 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2205 " TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2206 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2207 " ModelViewProjectionPosition = gl_Position;\n"
2211 "#ifdef FRAGMENT_SHADER\n"
2214 "float2 TexCoord : TEXCOORD0,\n"
2215 "float3 EyeVector : TEXCOORD1,\n"
2216 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2217 "uniform sampler Texture_Normal : register(s0),\n"
2218 "uniform sampler Texture_Refraction : register(s3),\n"
2219 "uniform sampler Texture_Reflection : register(s7),\n"
2220 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2221 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2222 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2223 "uniform float4 RefractColor : register(c29),\n"
2224 "out float4 gl_FragColor : COLOR\n"
2227 " float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2228 " //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"
2229 " float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2230 " float2 ScreenTexCoord = SafeScreenTexCoord + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy * DistortScaleRefractReflect.xy;\n"
2231 " // FIXME temporary hack to detect the case that the reflection\n"
2232 " // gets blackened at edges due to leaving the area that contains actual\n"
2234 " // Remove this 'ack once we have a better way to stop this thing from\n"
2236 " float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2237 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2238 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2239 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2240 " ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2241 " gl_FragColor = float4(tex2D(Texture_Refraction, ScreenTexCoord).rgb, 1) * RefractColor;\n"
2244 "#else // !MODE_REFRACTION\n"
2249 "#ifdef MODE_WATER\n"
2250 "#ifdef VERTEX_SHADER\n"
2254 "float4 gl_Vertex : POSITION,\n"
2255 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2256 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2257 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2258 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2259 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2260 "uniform float4x4 TexMatrix : register(c0),\n"
2261 "uniform float3 EyePosition : register(c24),\n"
2262 "out float4 gl_Position : POSITION,\n"
2263 "out float2 TexCoord : TEXCOORD0,\n"
2264 "out float3 EyeVector : TEXCOORD1,\n"
2265 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2268 " TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2269 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2270 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2271 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2272 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2273 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2274 " ModelViewProjectionPosition = gl_Position;\n"
2278 "#ifdef FRAGMENT_SHADER\n"
2281 "float2 TexCoord : TEXCOORD0,\n"
2282 "float3 EyeVector : TEXCOORD1,\n"
2283 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2284 "uniform sampler Texture_Normal : register(s0),\n"
2285 "uniform sampler Texture_Refraction : register(s3),\n"
2286 "uniform sampler Texture_Reflection : register(s7),\n"
2287 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2288 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2289 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2290 "uniform float4 RefractColor : register(c29),\n"
2291 "uniform float4 ReflectColor : register(c26),\n"
2292 "uniform float ReflectFactor : register(c27),\n"
2293 "uniform float ReflectOffset : register(c28),\n"
2294 "out float4 gl_FragColor : COLOR\n"
2297 " float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2298 " //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2299 " float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2300 " //SafeScreenTexCoord = gl_FragCoord.xyxy * float4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
2301 " float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy).xyxy * DistortScaleRefractReflect;\n"
2302 " // FIXME temporary hack to detect the case that the reflection\n"
2303 " // gets blackened at edges due to leaving the area that contains actual\n"
2305 " // Remove this 'ack once we have a better way to stop this thing from\n"
2307 " float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2308 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2309 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2310 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2311 " ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2312 " f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2313 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2314 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2315 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2316 " ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2317 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2318 " gl_FragColor = lerp(float4(tex2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, float4(tex2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
2321 "#else // !MODE_WATER\n"
2326 "// 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"
2328 "// fragment shader specific:\n"
2329 "#ifdef FRAGMENT_SHADER\n"
2332 "float3 FogVertex(float3 surfacecolor, float3 FogColor, float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler Texture_FogMask, sampler Texture_FogHeightTexture)\n"
2335 "#ifdef USEFOGHEIGHTTEXTURE\n"
2336 " float4 fogheightpixel = tex2D(Texture_FogHeightTexture, float2(1,1) + float2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
2337 " fogfrac = fogheightpixel.a;\n"
2338 " return lerp(fogheightpixel.rgb * FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2340 "# ifdef USEFOGOUTSIDE\n"
2341 " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2343 " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2345 " return lerp(FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2350 "#ifdef USEOFFSETMAPPING\n"
2351 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler Texture_Normal)\n"
2353 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2354 " // 14 sample relief mapping: linear search and then binary search\n"
2355 " // this basically steps forward a small amount repeatedly until it finds\n"
2356 " // itself inside solid, then jitters forward and back using decreasing\n"
2357 " // amounts to find the impact\n"
2358 " //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2359 " //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2360 " float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2361 " float3 RT = float3(TexCoord, 1);\n"
2362 " OffsetVector *= 0.1;\n"
2363 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2364 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2365 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2366 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2367 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2368 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2369 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2370 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2371 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2372 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
2373 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
2374 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
2375 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
2376 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2379 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2380 " // this basically moves forward the full distance, and then backs up based\n"
2381 " // on height of samples\n"
2382 " //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2383 " //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2384 " float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2385 " TexCoord += OffsetVector;\n"
2386 " OffsetVector *= 0.333;\n"
2387 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2388 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2389 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2390 " return TexCoord;\n"
2393 "#endif // USEOFFSETMAPPING\n"
2395 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2396 "#if defined(USESHADOWMAP2D)\n"
2397 "# ifdef USESHADOWMAPORTHO\n"
2398 "# define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n"
2400 "# ifdef USESHADOWMAPVSDCT\n"
2401 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2403 " float3 adir = abs(dir);\n"
2404 " float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
2405 " float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2406 " return float3(lerp(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2409 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2411 " float3 adir = abs(dir);\n"
2412 " float ma = adir.z;\n"
2413 " float4 proj = float4(dir, 2.5);\n"
2414 " if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
2415 " if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
2417 " 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"
2419 " float2 aparams = ShadowMap_Parameters.xy / ma;\n"
2420 " 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"
2425 "#endif // defined(USESHADOWMAP2D)\n"
2427 "# ifdef USESHADOWMAP2D\n"
2428 "#ifdef USESHADOWMAPVSDCT\n"
2429 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2431 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2434 "#ifdef USESHADOWMAPVSDCT\n"
2435 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2437 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2441 "# ifdef USESHADOWSAMPLER\n"
2442 "# ifdef USESHADOWMAPPCF\n"
2443 "# define texval(x, y) tex2Dproj(Texture_ShadowMap2D, float4(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r \n"
2444 " float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2445 " 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"
2447 " f = tex2Dproj(Texture_ShadowMap2D, float4(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r;\n"
2450 "# ifdef USESHADOWMAPPCF\n"
2451 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2452 "# ifdef GL_ARB_texture_gather\n"
2453 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, int2(x, y))\n"
2455 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)\n"
2457 " float2 offset = frac(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
2458 "# if USESHADOWMAPPCF > 1\n"
2459 " float4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
2460 " float4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
2461 " float4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
2462 " float4 group4 = step(shadowmaptc.z, texval(-2.0, 0.0));\n"
2463 " float4 group5 = step(shadowmaptc.z, texval( 0.0, 0.0));\n"
2464 " float4 group6 = step(shadowmaptc.z, texval( 2.0, 0.0));\n"
2465 " float4 group7 = step(shadowmaptc.z, texval(-2.0, 2.0));\n"
2466 " float4 group8 = step(shadowmaptc.z, texval( 0.0, 2.0));\n"
2467 " float4 group9 = step(shadowmaptc.z, texval( 2.0, 2.0));\n"
2468 " float4 locols = float4(group1.ab, group3.ab);\n"
2469 " float4 hicols = float4(group7.rg, group9.rg);\n"
2470 " locols.yz += group2.ab;\n"
2471 " hicols.yz += group8.rg;\n"
2472 " float4 midcols = float4(group1.rg, group3.rg) + float4(group7.ab, group9.ab) +\n"
2473 " float4(group4.rg, group6.rg) + float4(group4.ab, group6.ab) +\n"
2474 " lerp(locols, hicols, offset.y);\n"
2475 " float4 cols = group5 + float4(group2.rg, group8.ab);\n"
2476 " cols.xyz += lerp(midcols.xyz, midcols.yzw, offset.x);\n"
2477 " f = dot(cols, float4(1.0/25.0));\n"
2479 " float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2480 " float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2481 " float4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
2482 " float4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
2483 " float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2484 " lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2485 " f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2488 "# ifdef GL_EXT_gpu_shader4\n"
2489 "# define texval(x, y) tex2DOffset(Texture_ShadowMap2D, center, int2(x, y)).r\n"
2491 "# define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale).r \n"
2493 "# if USESHADOWMAPPCF > 1\n"
2494 " float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2495 " center *= ShadowMap_TextureScale;\n"
2496 " 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"
2497 " 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"
2498 " 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"
2499 " 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"
2500 " float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2501 " f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2503 " float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2504 " float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2505 " float3 row2 = step(shadowmaptc.z, float3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
2506 " float3 row3 = step(shadowmaptc.z, float3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
2507 " float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2508 " f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25,0.25));\n"
2512 " f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2515 "# ifdef USESHADOWMAPORTHO\n"
2516 " return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2522 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
2523 "#endif // FRAGMENT_SHADER\n"
2528 "#ifdef MODE_DEFERREDGEOMETRY\n"
2529 "#ifdef VERTEX_SHADER\n"
2532 "float4 gl_Vertex : POSITION,\n"
2533 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2534 "#ifdef USEVERTEXTEXTUREBLEND\n"
2535 "float4 gl_Color : COLOR0,\n"
2537 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2538 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2539 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2540 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2541 "uniform float4x4 TexMatrix : register(c0),\n"
2542 "#ifdef USEVERTEXTEXTUREBLEND\n"
2543 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2545 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2546 "#ifdef USEOFFSETMAPPING\n"
2547 "uniform float3 EyePosition : register(c24),\n"
2549 "out float4 gl_Position : POSITION,\n"
2550 "#ifdef USEVERTEXTEXTUREBLEND\n"
2551 "out float4 gl_FrontColor : COLOR,\n"
2553 "out float4 TexCoordBoth : TEXCOORD0,\n"
2554 "#ifdef USEOFFSETMAPPING\n"
2555 "out float3 EyeVector : TEXCOORD2,\n"
2557 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2558 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2559 "out float4 VectorR : TEXCOORD7 // direction of R texcoord (surface normal), Depth value\n"
2562 " TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2563 "#ifdef USEVERTEXTEXTUREBLEND\n"
2565 " gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2567 " gl_FrontColor = gl_Color; // Cg is forward\n"
2569 " TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2572 " // transform unnormalized eye direction into tangent space\n"
2573 "#ifdef USEOFFSETMAPPING\n"
2574 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2575 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2576 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2577 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2580 " VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2581 " VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2582 " VectorR.xyz = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2583 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2584 " VectorR.w = gl_Position.z;\n"
2586 "#endif // VERTEX_SHADER\n"
2588 "#ifdef FRAGMENT_SHADER\n"
2591 "float4 TexCoordBoth : TEXCOORD0,\n"
2592 "float3 EyeVector : TEXCOORD2,\n"
2593 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2594 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2595 "float4 VectorR : TEXCOORD7, // direction of R texcoord (surface normal), Depth value\n"
2596 "uniform sampler Texture_Normal : register(s0),\n"
2597 "#ifdef USEALPHAKILL\n"
2598 "uniform sampler Texture_Color : register(s1),\n"
2600 "uniform sampler Texture_Gloss : register(s2),\n"
2601 "#ifdef USEVERTEXTEXTUREBLEND\n"
2602 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2603 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2605 "#ifdef USEOFFSETMAPPING\n"
2606 "uniform float OffsetMapping_Scale : register(c24),\n"
2608 "uniform half SpecularPower : register(c36),\n"
2610 "out float4 gl_FragData0 : COLOR0,\n"
2611 "out float4 gl_FragData1 : COLOR1\n"
2613 "out float4 gl_FragColor : COLOR\n"
2617 " float2 TexCoord = TexCoordBoth.xy;\n"
2618 "#ifdef USEOFFSETMAPPING\n"
2619 " // apply offsetmapping\n"
2620 " float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2621 "#define TexCoord TexCoordOffset\n"
2624 "#ifdef USEALPHAKILL\n"
2625 " if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2629 "#ifdef USEVERTEXTEXTUREBLEND\n"
2630 " float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2631 " float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2632 " //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2633 " //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2636 "#ifdef USEVERTEXTEXTUREBLEND\n"
2637 " float3 surfacenormal = lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend) - float3(0.5, 0.5, 0.5);\n"
2638 " float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2).a, tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
2640 " float3 surfacenormal = tex2D(Texture_Normal, TexCoord).rgb - float3(0.5, 0.5, 0.5);\n"
2641 " float a = tex2D(Texture_Gloss, TexCoord).a;\n"
2645 " 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"
2646 " float Depth = VectorR.w / 256.0;\n"
2647 " float4 depthcolor = float4(Depth,Depth*65536.0/255.0,Depth*16777216.0/255.0,0.0);\n"
2648 "// float4 depthcolor = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
2649 " depthcolor.yz -= floor(depthcolor.yz);\n"
2650 " gl_FragData1 = depthcolor;\n"
2652 " gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), a);\n"
2655 "#endif // FRAGMENT_SHADER\n"
2656 "#else // !MODE_DEFERREDGEOMETRY\n"
2661 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2662 "#ifdef VERTEX_SHADER\n"
2665 "float4 gl_Vertex : POSITION,\n"
2666 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2667 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2668 "out float4 gl_Position : POSITION,\n"
2669 "out float4 ModelViewPosition : TEXCOORD0\n"
2672 " ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2673 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2675 "#endif // VERTEX_SHADER\n"
2677 "#ifdef FRAGMENT_SHADER\n"
2681 "float2 Pixel : VPOS,\n"
2683 "float2 Pixel : WPOS,\n"
2685 "float4 ModelViewPosition : TEXCOORD0,\n"
2686 "uniform float4x4 ViewToLight : register(c44),\n"
2687 "uniform float2 ScreenToDepth : register(c33), // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2688 "uniform float3 LightPosition : register(c23),\n"
2689 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
2690 "uniform half3 DeferredColor_Ambient : register(c9),\n"
2691 "uniform half3 DeferredColor_Diffuse : register(c10),\n"
2692 "#ifdef USESPECULAR\n"
2693 "uniform half3 DeferredColor_Specular : register(c11),\n"
2694 "uniform half SpecularPower : register(c36),\n"
2696 "uniform sampler Texture_Attenuation : register(s9),\n"
2697 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2698 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2700 "#ifdef USECUBEFILTER\n"
2701 "uniform samplerCUBE Texture_Cube : register(s10),\n"
2704 "#ifdef USESHADOWMAP2D\n"
2705 "# ifdef USESHADOWSAMPLER\n"
2706 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2708 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2712 "#ifdef USESHADOWMAPVSDCT\n"
2713 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
2716 "#if defined(USESHADOWMAP2D)\n"
2717 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
2718 "uniform float4 ShadowMap_Parameters : register(c34),\n"
2721 "out float4 gl_FragData0 : COLOR0,\n"
2722 "out float4 gl_FragData1 : COLOR1\n"
2725 " // calculate viewspace pixel position\n"
2726 " float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2727 " //ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2728 " float3 position;\n"
2730 " position.z = texDepth2D(Texture_ScreenDepth, ScreenTexCoord) * 256.0;\n"
2732 " position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2734 " position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2735 " // decode viewspace pixel normal\n"
2736 " half4 normalmap = half4(tex2D(Texture_ScreenNormalMap, ScreenTexCoord));\n"
2737 " half3 surfacenormal = half3(normalize(normalmap.rgb - half3(0.5,0.5,0.5)));\n"
2738 " // surfacenormal = pixel normal in viewspace\n"
2739 " // LightVector = pixel to light in viewspace\n"
2740 " // CubeVector = position in lightspace\n"
2741 " // eyevector = pixel to view in viewspace\n"
2742 " float3 CubeVector = mul(ViewToLight, float4(position,1)).xyz;\n"
2743 " half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
2744 "#ifdef USEDIFFUSE\n"
2745 " // calculate diffuse shading\n"
2746 " half3 lightnormal = half3(normalize(LightPosition - position));\n"
2747 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2749 "#ifdef USESPECULAR\n"
2750 " // calculate directional shading\n"
2751 " float3 eyevector = position * -1.0;\n"
2752 "# ifdef USEEXACTSPECULARMATH\n"
2753 " half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a));\n"
2755 " half3 specularnormal = half3(normalize(lightnormal + half3(normalize(eyevector))));\n"
2756 " half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a));\n"
2760 "#if defined(USESHADOWMAP2D)\n"
2761 " fade *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2762 "#ifdef USESHADOWMAPVSDCT\n"
2763 ", Texture_CubeProjection\n"
2768 "#ifdef USEDIFFUSE\n"
2769 " gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2771 " gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2773 "#ifdef USESPECULAR\n"
2774 " gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2776 " gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2779 "# ifdef USECUBEFILTER\n"
2780 " float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2781 " gl_FragData0.rgb *= cubecolor;\n"
2782 " gl_FragData1.rgb *= cubecolor;\n"
2785 "#endif // FRAGMENT_SHADER\n"
2786 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2791 "#ifdef VERTEX_SHADER\n"
2794 "float4 gl_Vertex : POSITION,\n"
2795 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2796 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2797 "float4 gl_Color : COLOR0,\n"
2799 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2800 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2801 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2802 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2803 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2805 "uniform float3 EyePosition : register(c24),\n"
2806 "uniform float4x4 TexMatrix : register(c0),\n"
2807 "#ifdef USEVERTEXTEXTUREBLEND\n"
2808 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2810 "#ifdef MODE_LIGHTSOURCE\n"
2811 "uniform float4x4 ModelToLight : register(c20),\n"
2813 "#ifdef MODE_LIGHTSOURCE\n"
2814 "uniform float3 LightPosition : register(c27),\n"
2816 "#ifdef MODE_LIGHTDIRECTION\n"
2817 "uniform float3 LightDir : register(c26),\n"
2819 "uniform float4 FogPlane : register(c25),\n"
2820 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2821 "uniform float3 LightPosition : register(c27),\n"
2823 "#ifdef USESHADOWMAPORTHO\n"
2824 "uniform float4x4 ShadowMapMatrix : register(c16),\n"
2826 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2827 "out float4 gl_FrontColor : COLOR,\n"
2829 "out float4 TexCoordBoth : TEXCOORD0,\n"
2830 "#ifdef USELIGHTMAP\n"
2831 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2833 "#ifdef USEEYEVECTOR\n"
2834 "out float3 EyeVector : TEXCOORD2,\n"
2836 "#ifdef USEREFLECTION\n"
2837 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2840 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2842 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE) || defined(USEDIFFUSE)\n"
2843 "out float3 LightVector : TEXCOORD1,\n"
2845 "#ifdef MODE_LIGHTSOURCE\n"
2846 "out float3 CubeVector : TEXCOORD3,\n"
2848 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2849 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2850 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2851 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2853 "#ifdef USESHADOWMAPORTHO\n"
2854 "out float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2856 "out float4 gl_Position : POSITION\n"
2859 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2861 " gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2863 " gl_FrontColor = gl_Color; // Cg is forward\n"
2866 " // copy the surface texcoord\n"
2867 " TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2868 "#ifdef USEVERTEXTEXTUREBLEND\n"
2869 " TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2871 "#ifdef USELIGHTMAP\n"
2872 " TexCoordLightmap = gl_MultiTexCoord4.xy;\n"
2875 "#ifdef MODE_LIGHTSOURCE\n"
2876 " // transform vertex position into light attenuation/cubemap space\n"
2877 " // (-1 to +1 across the light box)\n"
2878 " CubeVector = mul(ModelToLight, gl_Vertex).xyz;\n"
2880 "# ifdef USEDIFFUSE\n"
2881 " // transform unnormalized light direction into tangent space\n"
2882 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
2883 " // normalize it per pixel)\n"
2884 " float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2885 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2886 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2887 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2891 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2892 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2893 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2894 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2897 " // transform unnormalized eye direction into tangent space\n"
2898 "#ifdef USEEYEVECTOR\n"
2899 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2900 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2901 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2902 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2906 " EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2907 " EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2910 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2911 " VectorS = gl_MultiTexCoord1.xyz;\n"
2912 " VectorT = gl_MultiTexCoord2.xyz;\n"
2913 " VectorR = gl_MultiTexCoord3.xyz;\n"
2916 " // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2917 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2919 "#ifdef USESHADOWMAPORTHO\n"
2920 " ShadowMapTC = mul(ShadowMapMatrix, gl_Position).xyz;\n"
2923 "#ifdef USEREFLECTION\n"
2924 " ModelViewProjectionPosition = gl_Position;\n"
2927 "#endif // VERTEX_SHADER\n"
2932 "#ifdef FRAGMENT_SHADER\n"
2935 "#ifdef USEDEFERREDLIGHTMAP\n"
2937 "float2 Pixel : VPOS,\n"
2939 "float2 Pixel : WPOS,\n"
2942 "float4 gl_FrontColor : COLOR,\n"
2943 "float4 TexCoordBoth : TEXCOORD0,\n"
2944 "#ifdef USELIGHTMAP\n"
2945 "float2 TexCoordLightmap : TEXCOORD1,\n"
2947 "#ifdef USEEYEVECTOR\n"
2948 "float3 EyeVector : TEXCOORD2,\n"
2950 "#ifdef USEREFLECTION\n"
2951 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2954 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2956 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2957 "float3 LightVector : TEXCOORD1,\n"
2959 "#ifdef MODE_LIGHTSOURCE\n"
2960 "float3 CubeVector : TEXCOORD3,\n"
2962 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2963 "float4 ModelViewPosition : TEXCOORD0,\n"
2965 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2966 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2967 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2968 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2970 "#ifdef USESHADOWMAPORTHO\n"
2971 "float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2974 "uniform sampler Texture_Normal : register(s0),\n"
2975 "uniform sampler Texture_Color : register(s1),\n"
2976 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2977 "uniform sampler Texture_Gloss : register(s2),\n"
2980 "uniform sampler Texture_Glow : register(s3),\n"
2982 "#ifdef USEVERTEXTEXTUREBLEND\n"
2983 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2984 "uniform sampler Texture_SecondaryColor : register(s5),\n"
2985 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2986 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2989 "uniform sampler Texture_SecondaryGlow : register(s7),\n"
2992 "#ifdef USECOLORMAPPING\n"
2993 "uniform sampler Texture_Pants : register(s4),\n"
2994 "uniform sampler Texture_Shirt : register(s7),\n"
2997 "uniform sampler Texture_FogHeightTexture : register(s14),\n"
2998 "uniform sampler Texture_FogMask : register(s8),\n"
3000 "#ifdef USELIGHTMAP\n"
3001 "uniform sampler Texture_Lightmap : register(s9),\n"
3003 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
3004 "uniform sampler Texture_Deluxemap : register(s10),\n"
3006 "#ifdef USEREFLECTION\n"
3007 "uniform sampler Texture_Reflection : register(s7),\n"
3010 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
3011 "uniform sampler Texture_ScreenDepth : register(s13),\n"
3012 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
3014 "#ifdef USEDEFERREDLIGHTMAP\n"
3015 "uniform sampler Texture_ScreenDepth : register(s13),\n"
3016 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
3017 "uniform sampler Texture_ScreenDiffuse : register(s11),\n"
3018 "uniform sampler Texture_ScreenSpecular : register(s12),\n"
3021 "#ifdef USECOLORMAPPING\n"
3022 "uniform half3 Color_Pants : register(c7),\n"
3023 "uniform half3 Color_Shirt : register(c8),\n"
3026 "uniform float3 FogColor : register(c16),\n"
3027 "uniform float FogRangeRecip : register(c20),\n"
3028 "uniform float FogPlaneViewDist : register(c19),\n"
3029 "uniform float FogHeightFade : register(c17),\n"
3032 "#ifdef USEOFFSETMAPPING\n"
3033 "uniform float OffsetMapping_Scale : register(c24),\n"
3036 "#ifdef USEDEFERREDLIGHTMAP\n"
3037 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
3038 "uniform half3 DeferredMod_Diffuse : register(c12),\n"
3039 "uniform half3 DeferredMod_Specular : register(c13),\n"
3041 "uniform half3 Color_Ambient : register(c3),\n"
3042 "uniform half3 Color_Diffuse : register(c4),\n"
3043 "uniform half3 Color_Specular : register(c5),\n"
3044 "uniform half SpecularPower : register(c36),\n"
3046 "uniform half3 Color_Glow : register(c6),\n"
3048 "uniform half Alpha : register(c0),\n"
3049 "#ifdef USEREFLECTION\n"
3050 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
3051 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
3052 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
3053 "uniform half4 ReflectColor : register(c26),\n"
3055 "#ifdef USEREFLECTCUBE\n"
3056 "uniform float4x4 ModelToReflectCube : register(c48),\n"
3057 "uniform sampler Texture_ReflectMask : register(s5),\n"
3058 "uniform samplerCUBE Texture_ReflectCube : register(s6),\n"
3060 "#ifdef MODE_LIGHTDIRECTION\n"
3061 "uniform half3 LightColor : register(c21),\n"
3063 "#ifdef MODE_LIGHTSOURCE\n"
3064 "uniform half3 LightColor : register(c21),\n"
3067 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
3068 "uniform sampler Texture_Attenuation : register(s9),\n"
3069 "uniform samplerCUBE Texture_Cube : register(s10),\n"
3072 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
3074 "#ifdef USESHADOWMAP2D\n"
3075 "# ifdef USESHADOWSAMPLER\n"
3076 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
3078 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
3082 "#ifdef USESHADOWMAPVSDCT\n"
3083 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
3086 "#if defined(USESHADOWMAP2D)\n"
3087 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
3088 "uniform float4 ShadowMap_Parameters : register(c34),\n"
3090 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
3092 "out float4 gl_FragColor : COLOR\n"
3095 " float2 TexCoord = TexCoordBoth.xy;\n"
3096 "#ifdef USEVERTEXTEXTUREBLEND\n"
3097 " float2 TexCoord2 = TexCoordBoth.zw;\n"
3099 "#ifdef USEOFFSETMAPPING\n"
3100 " // apply offsetmapping\n"
3101 " float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
3102 "#define TexCoord TexCoordOffset\n"
3105 " // combine the diffuse textures (base, pants, shirt)\n"
3106 " half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
3107 "#ifdef USEALPHAKILL\n"
3108 " if (color.a < 0.5)\n"
3111 " color.a *= Alpha;\n"
3112 "#ifdef USECOLORMAPPING\n"
3113 " color.rgb += half3(tex2D(Texture_Pants, TexCoord).rgb) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord).rgb) * Color_Shirt;\n"
3115 "#ifdef USEVERTEXTEXTUREBLEND\n"
3116 " half terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
3117 " //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
3118 " //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
3119 " color.rgb = half3(lerp(tex2D(Texture_SecondaryColor, TexCoord2).rgb, float3(color.rgb), terrainblend));\n"
3121 " //color = half4(lerp(float4(1, 0, 0, 1), color, terrainblend));\n"
3124 " // get the surface normal\n"
3125 "#ifdef USEVERTEXTEXTUREBLEND\n"
3126 " half3 surfacenormal = normalize(half3(lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend)) - half3(0.5, 0.5, 0.5));\n"
3128 " half3 surfacenormal = half3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5, 0.5, 0.5)));\n"
3131 " // get the material colors\n"
3132 " half3 diffusetex = color.rgb;\n"
3133 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3134 "# ifdef USEVERTEXTEXTUREBLEND\n"
3135 " half4 glosstex = half4(lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord), terrainblend));\n"
3137 " half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
3141 "#ifdef USEREFLECTCUBE\n"
3142 " float3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
3143 " float3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
3144 " float3 ReflectCubeTexCoord = mul(ModelToReflectCube, float4(ModelReflectVector, 0)).xyz;\n"
3145 " diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord).rgb) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord).rgb);\n"
3151 "#ifdef MODE_LIGHTSOURCE\n"
3152 " // light source\n"
3153 "#ifdef USEDIFFUSE\n"
3154 " half3 lightnormal = half3(normalize(LightVector));\n"
3155 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3156 " color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
3157 "#ifdef USESPECULAR\n"
3158 "#ifdef USEEXACTSPECULARMATH\n"
3159 " half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3161 " half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3162 " half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3164 " color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
3167 " color.rgb = diffusetex * Color_Ambient;\n"
3169 " color.rgb *= LightColor;\n"
3170 " color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
3171 "#if defined(USESHADOWMAP2D)\n"
3172 " color.rgb *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3173 "#ifdef USESHADOWMAPVSDCT\n"
3174 ", Texture_CubeProjection\n"
3179 "# ifdef USECUBEFILTER\n"
3180 " color.rgb *= half3(texCUBE(Texture_Cube, CubeVector).rgb);\n"
3183 "#ifdef USESHADOWMAP2D\n"
3184 "#ifdef USESHADOWMAPVSDCT\n"
3185 "// float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters, Texture_CubeProjection);\n"
3187 "// float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters);\n"
3189 "// color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3190 "// color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3191 "// color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3192 "// color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3193 "// color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3194 "// color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3195 "// color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3196 "// color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3197 "// color.r = half(shadowmaptc.z - texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3198 "// color.r = half(shadowmaptc.z);\n"
3199 "// color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3200 "// color.r = half(shadowmaptc.z);\n"
3202 "// color.rgb = abs(CubeVector);\n"
3204 "// color.rgb = half3(1,1,1);\n"
3205 "#endif // MODE_LIGHTSOURCE\n"
3210 "#ifdef MODE_LIGHTDIRECTION\n"
3212 "#ifdef USEDIFFUSE\n"
3213 " half3 lightnormal = half3(normalize(LightVector));\n"
3215 "#define lightcolor LightColor\n"
3216 "#endif // MODE_LIGHTDIRECTION\n"
3217 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3219 " // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3220 " half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3221 " half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3222 " // convert modelspace light vector to tangentspace\n"
3223 " half3 lightnormal;\n"
3224 " lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3225 " lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3226 " lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3227 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3228 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3229 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3230 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3231 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3232 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3233 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3234 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3235 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3236 " lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3237 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3238 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3240 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3241 " half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3242 " half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3248 "#ifdef MODE_FAKELIGHT\n"
3250 "half3 lightnormal = half3(normalize(EyeVector));\n"
3251 "half3 lightcolor = half3(1.0,1.0,1.0);\n"
3252 "#endif // MODE_FAKELIGHT\n"
3257 "#ifdef MODE_LIGHTMAP\n"
3258 " color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb) * Color_Diffuse);\n"
3259 "#endif // MODE_LIGHTMAP\n"
3260 "#ifdef MODE_VERTEXCOLOR\n"
3261 " color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3262 "#endif // MODE_VERTEXCOLOR\n"
3263 "#ifdef MODE_FLATCOLOR\n"
3264 " color.rgb = diffusetex * Color_Ambient;\n"
3265 "#endif // MODE_FLATCOLOR\n"
3271 "# ifdef USEDIFFUSE\n"
3272 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3273 "# ifdef USESPECULAR\n"
3274 "# ifdef USEEXACTSPECULARMATH\n"
3275 " half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3277 " half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3278 " half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3280 " color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3282 " color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3285 " color.rgb = diffusetex * Color_Ambient;\n"
3289 "#ifdef USESHADOWMAPORTHO\n"
3290 " color.rgb *= half(ShadowMapCompare(ShadowMapTC, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale));\n"
3293 "#ifdef USEDEFERREDLIGHTMAP\n"
3294 " float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3295 " color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord).rgb) * DeferredMod_Diffuse;\n"
3296 " color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord).rgb) * DeferredMod_Specular;\n"
3297 "// color.rgb = half3(tex2D(Texture_ScreenDepth, ScreenTexCoord).rgb);\n"
3298 "// color.r = half(texDepth2D(Texture_ScreenDepth, ScreenTexCoord)) * 1.0;\n"
3302 "#ifdef USEVERTEXTEXTUREBLEND\n"
3303 " color.rgb += half3(lerp(tex2D(Texture_SecondaryGlow, TexCoord2).rgb, tex2D(Texture_Glow, TexCoord).rgb, terrainblend)) * Color_Glow;\n"
3305 " color.rgb += half3(tex2D(Texture_Glow, TexCoord).rgb) * Color_Glow;\n"
3310 " color.rgb = FogVertex(color.rgb, FogColor, EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask, Texture_FogHeightTexture);\n"
3313 " // 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"
3314 "#ifdef USEREFLECTION\n"
3315 " float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3316 " //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3317 " float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3318 " float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.zw;\n"
3319 " // FIXME temporary hack to detect the case that the reflection\n"
3320 " // gets blackened at edges due to leaving the area that contains actual\n"
3322 " // Remove this 'ack once we have a better way to stop this thing from\n"
3324 " float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3325 " 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 " ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3329 " color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord).rgb) * ReflectColor.rgb, ReflectColor.a);\n"
3332 " gl_FragColor = float4(color);\n"
3334 "#endif // FRAGMENT_SHADER\n"
3336 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3337 "#endif // !MODE_DEFERREDGEOMETRY\n"
3338 "#endif // !MODE_WATER\n"
3339 "#endif // !MODE_REFRACTION\n"
3340 "#endif // !MODE_BLOOMBLUR\n"
3341 "#endif // !MODE_GENERIC\n"
3342 "#endif // !MODE_POSTPROCESS\n"
3343 "#endif // !MODE_SHOWDEPTH\n"
3344 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3347 char *glslshaderstring = NULL;
3348 char *hlslshaderstring = NULL;
3350 //=======================================================================================================================================================
3352 typedef struct shaderpermutationinfo_s
3354 const char *pretext;
3357 shaderpermutationinfo_t;
3359 typedef struct shadermodeinfo_s
3361 const char *vertexfilename;
3362 const char *geometryfilename;
3363 const char *fragmentfilename;
3364 const char *pretext;
3369 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3370 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3372 {"#define USEDIFFUSE\n", " diffuse"},
3373 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3374 {"#define USEVIEWTINT\n", " viewtint"},
3375 {"#define USECOLORMAPPING\n", " colormapping"},
3376 {"#define USESATURATION\n", " saturation"},
3377 {"#define USEFOGINSIDE\n", " foginside"},
3378 {"#define USEFOGOUTSIDE\n", " fogoutside"},
3379 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
3380 {"#define USEGAMMARAMPS\n", " gammaramps"},
3381 {"#define USECUBEFILTER\n", " cubefilter"},
3382 {"#define USEGLOW\n", " glow"},
3383 {"#define USEBLOOM\n", " bloom"},
3384 {"#define USESPECULAR\n", " specular"},
3385 {"#define USEPOSTPROCESSING\n", " postprocessing"},
3386 {"#define USEREFLECTION\n", " reflection"},
3387 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3388 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3389 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3390 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3391 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3392 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3393 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3394 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
3395 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3396 {"#define USEALPHAKILL\n", " alphakill"},
3397 {"#define USEREFLECTCUBE\n", " reflectcube"},
3398 {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
3401 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3402 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3404 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3405 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3406 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3407 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3408 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3409 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3410 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
3411 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3412 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3413 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3414 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3415 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3416 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3417 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3418 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3419 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3422 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
3424 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
3425 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3426 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3427 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3428 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3429 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3430 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
3431 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3432 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3433 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3434 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3435 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
3436 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
3437 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3438 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3439 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3442 struct r_glsl_permutation_s;
3443 typedef struct r_glsl_permutation_s
3445 /// hash lookup data
3446 struct r_glsl_permutation_s *hashnext;
3448 unsigned int permutation;
3450 /// indicates if we have tried compiling this permutation already
3452 /// 0 if compilation failed
3454 // texture units assigned to each detected uniform
3455 int tex_Texture_First;
3456 int tex_Texture_Second;
3457 int tex_Texture_GammaRamps;
3458 int tex_Texture_Normal;
3459 int tex_Texture_Color;
3460 int tex_Texture_Gloss;
3461 int tex_Texture_Glow;
3462 int tex_Texture_SecondaryNormal;
3463 int tex_Texture_SecondaryColor;
3464 int tex_Texture_SecondaryGloss;
3465 int tex_Texture_SecondaryGlow;
3466 int tex_Texture_Pants;
3467 int tex_Texture_Shirt;
3468 int tex_Texture_FogHeightTexture;
3469 int tex_Texture_FogMask;
3470 int tex_Texture_Lightmap;
3471 int tex_Texture_Deluxemap;
3472 int tex_Texture_Attenuation;
3473 int tex_Texture_Cube;
3474 int tex_Texture_Refraction;
3475 int tex_Texture_Reflection;
3476 int tex_Texture_ShadowMap2D;
3477 int tex_Texture_CubeProjection;
3478 int tex_Texture_ScreenDepth;
3479 int tex_Texture_ScreenNormalMap;
3480 int tex_Texture_ScreenDiffuse;
3481 int tex_Texture_ScreenSpecular;
3482 int tex_Texture_ReflectMask;
3483 int tex_Texture_ReflectCube;
3484 /// locations of detected uniforms in program object, or -1 if not found
3485 int loc_Texture_First;
3486 int loc_Texture_Second;
3487 int loc_Texture_GammaRamps;
3488 int loc_Texture_Normal;
3489 int loc_Texture_Color;
3490 int loc_Texture_Gloss;
3491 int loc_Texture_Glow;
3492 int loc_Texture_SecondaryNormal;
3493 int loc_Texture_SecondaryColor;
3494 int loc_Texture_SecondaryGloss;
3495 int loc_Texture_SecondaryGlow;
3496 int loc_Texture_Pants;
3497 int loc_Texture_Shirt;
3498 int loc_Texture_FogHeightTexture;
3499 int loc_Texture_FogMask;
3500 int loc_Texture_Lightmap;
3501 int loc_Texture_Deluxemap;
3502 int loc_Texture_Attenuation;
3503 int loc_Texture_Cube;
3504 int loc_Texture_Refraction;
3505 int loc_Texture_Reflection;
3506 int loc_Texture_ShadowMap2D;
3507 int loc_Texture_CubeProjection;
3508 int loc_Texture_ScreenDepth;
3509 int loc_Texture_ScreenNormalMap;
3510 int loc_Texture_ScreenDiffuse;
3511 int loc_Texture_ScreenSpecular;
3512 int loc_Texture_ReflectMask;
3513 int loc_Texture_ReflectCube;
3515 int loc_BloomBlur_Parameters;
3517 int loc_Color_Ambient;
3518 int loc_Color_Diffuse;
3519 int loc_Color_Specular;
3521 int loc_Color_Pants;
3522 int loc_Color_Shirt;
3523 int loc_DeferredColor_Ambient;
3524 int loc_DeferredColor_Diffuse;
3525 int loc_DeferredColor_Specular;
3526 int loc_DeferredMod_Diffuse;
3527 int loc_DeferredMod_Specular;
3528 int loc_DistortScaleRefractReflect;
3529 int loc_EyePosition;
3531 int loc_FogHeightFade;
3533 int loc_FogPlaneViewDist;
3534 int loc_FogRangeRecip;
3537 int loc_LightPosition;
3538 int loc_OffsetMapping_Scale;
3540 int loc_ReflectColor;
3541 int loc_ReflectFactor;
3542 int loc_ReflectOffset;
3543 int loc_RefractColor;
3545 int loc_ScreenCenterRefractReflect;
3546 int loc_ScreenScaleRefractReflect;
3547 int loc_ScreenToDepth;
3548 int loc_ShadowMap_Parameters;
3549 int loc_ShadowMap_TextureScale;
3550 int loc_SpecularPower;
3555 int loc_ViewTintColor;
3556 int loc_ViewToLight;
3557 int loc_ModelToLight;
3559 int loc_BackgroundTexMatrix;
3560 int loc_ModelViewProjectionMatrix;
3561 int loc_ModelViewMatrix;
3562 int loc_PixelToScreenTexCoord;
3563 int loc_ModelToReflectCube;
3564 int loc_ShadowMapMatrix;
3565 int loc_BloomColorSubtract;
3566 int loc_NormalmapScrollBlend;
3568 r_glsl_permutation_t;
3570 #define SHADERPERMUTATION_HASHSIZE 256
3573 // non-degradable "lightweight" shader parameters to keep the permutations simpler
3574 // these can NOT degrade! only use for simple stuff
3577 SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
3578 SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3579 SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
3580 SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
3581 SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
3582 SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5 ///< postprocess uservec4 is enabled
3584 #define SHADERSTATICPARMS_COUNT 6
3586 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
3587 static int shaderstaticparms_count = 0;
3589 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
3590 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
3591 qboolean R_CompileShader_CheckStaticParms(void)
3593 static int r_compileshader_staticparms_save[1];
3594 memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
3595 memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
3598 if (r_glsl_saturation_redcompensate.integer)
3599 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
3600 if (r_shadow_glossexact.integer)
3601 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
3602 if (r_glsl_postprocess.integer)
3604 if (r_glsl_postprocess_uservec1_enable.integer)
3605 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
3606 if (r_glsl_postprocess_uservec2_enable.integer)
3607 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
3608 if (r_glsl_postprocess_uservec3_enable.integer)
3609 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
3610 if (r_glsl_postprocess_uservec4_enable.integer)
3611 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
3613 return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
3616 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
3617 if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
3618 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
3620 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
3621 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
3623 shaderstaticparms_count = 0;
3626 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
3627 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
3628 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
3629 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
3630 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
3631 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
3634 /// information about each possible shader permutation
3635 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3636 /// currently selected permutation
3637 r_glsl_permutation_t *r_glsl_permutation;
3638 /// storage for permutations linked in the hash table
3639 memexpandablearray_t r_glsl_permutationarray;
3641 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3643 //unsigned int hashdepth = 0;
3644 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3645 r_glsl_permutation_t *p;
3646 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3648 if (p->mode == mode && p->permutation == permutation)
3650 //if (hashdepth > 10)
3651 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3656 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3658 p->permutation = permutation;
3659 p->hashnext = r_glsl_permutationhash[mode][hashindex];
3660 r_glsl_permutationhash[mode][hashindex] = p;
3661 //if (hashdepth > 10)
3662 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3666 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3669 if (!filename || !filename[0])
3671 if (!strcmp(filename, "glsl/default.glsl"))
3673 if (!glslshaderstring)
3675 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3676 if (glslshaderstring)
3677 Con_DPrintf("Loading shaders from file %s...\n", filename);
3679 glslshaderstring = (char *)builtinshaderstring;
3681 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3682 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3683 return shaderstring;
3685 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3688 if (printfromdisknotice)
3689 Con_DPrintf("from disk %s... ", filename);
3690 return shaderstring;
3692 return shaderstring;
3695 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3699 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3700 char *vertexstring, *geometrystring, *fragmentstring;
3701 char permutationname[256];
3702 int vertstrings_count = 0;
3703 int geomstrings_count = 0;
3704 int fragstrings_count = 0;
3705 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3706 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3707 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3714 permutationname[0] = 0;
3715 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
3716 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3717 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3719 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3721 // the first pretext is which type of shader to compile as
3722 // (later these will all be bound together as a program object)
3723 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3724 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3725 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3727 // the second pretext is the mode (for example a light source)
3728 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3729 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3730 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3731 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3733 // now add all the permutation pretexts
3734 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3736 if (permutation & (1<<i))
3738 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3739 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3740 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3741 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3745 // keep line numbers correct
3746 vertstrings_list[vertstrings_count++] = "\n";
3747 geomstrings_list[geomstrings_count++] = "\n";
3748 fragstrings_list[fragstrings_count++] = "\n";
3753 R_CompileShader_AddStaticParms(mode, permutation);
3754 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3755 vertstrings_count += shaderstaticparms_count;
3756 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3757 geomstrings_count += shaderstaticparms_count;
3758 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3759 fragstrings_count += shaderstaticparms_count;
3761 // now append the shader text itself
3762 vertstrings_list[vertstrings_count++] = vertexstring;
3763 geomstrings_list[geomstrings_count++] = geometrystring;
3764 fragstrings_list[fragstrings_count++] = fragmentstring;
3766 // if any sources were NULL, clear the respective list
3768 vertstrings_count = 0;
3769 if (!geometrystring)
3770 geomstrings_count = 0;
3771 if (!fragmentstring)
3772 fragstrings_count = 0;
3774 // compile the shader program
3775 if (vertstrings_count + geomstrings_count + fragstrings_count)
3776 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3780 qglUseProgram(p->program);CHECKGLERROR
3781 // look up all the uniform variable names we care about, so we don't
3782 // have to look them up every time we set them
3784 p->loc_Texture_First = qglGetUniformLocation(p->program, "Texture_First");
3785 p->loc_Texture_Second = qglGetUniformLocation(p->program, "Texture_Second");
3786 p->loc_Texture_GammaRamps = qglGetUniformLocation(p->program, "Texture_GammaRamps");
3787 p->loc_Texture_Normal = qglGetUniformLocation(p->program, "Texture_Normal");
3788 p->loc_Texture_Color = qglGetUniformLocation(p->program, "Texture_Color");
3789 p->loc_Texture_Gloss = qglGetUniformLocation(p->program, "Texture_Gloss");
3790 p->loc_Texture_Glow = qglGetUniformLocation(p->program, "Texture_Glow");
3791 p->loc_Texture_SecondaryNormal = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
3792 p->loc_Texture_SecondaryColor = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
3793 p->loc_Texture_SecondaryGloss = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
3794 p->loc_Texture_SecondaryGlow = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
3795 p->loc_Texture_Pants = qglGetUniformLocation(p->program, "Texture_Pants");
3796 p->loc_Texture_Shirt = qglGetUniformLocation(p->program, "Texture_Shirt");
3797 p->loc_Texture_FogHeightTexture = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
3798 p->loc_Texture_FogMask = qglGetUniformLocation(p->program, "Texture_FogMask");
3799 p->loc_Texture_Lightmap = qglGetUniformLocation(p->program, "Texture_Lightmap");
3800 p->loc_Texture_Deluxemap = qglGetUniformLocation(p->program, "Texture_Deluxemap");
3801 p->loc_Texture_Attenuation = qglGetUniformLocation(p->program, "Texture_Attenuation");
3802 p->loc_Texture_Cube = qglGetUniformLocation(p->program, "Texture_Cube");
3803 p->loc_Texture_Refraction = qglGetUniformLocation(p->program, "Texture_Refraction");
3804 p->loc_Texture_Reflection = qglGetUniformLocation(p->program, "Texture_Reflection");
3805 p->loc_Texture_ShadowMap2D = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
3806 p->loc_Texture_CubeProjection = qglGetUniformLocation(p->program, "Texture_CubeProjection");
3807 p->loc_Texture_ScreenDepth = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
3808 p->loc_Texture_ScreenNormalMap = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
3809 p->loc_Texture_ScreenDiffuse = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
3810 p->loc_Texture_ScreenSpecular = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
3811 p->loc_Texture_ReflectMask = qglGetUniformLocation(p->program, "Texture_ReflectMask");
3812 p->loc_Texture_ReflectCube = qglGetUniformLocation(p->program, "Texture_ReflectCube");
3813 p->loc_Alpha = qglGetUniformLocation(p->program, "Alpha");
3814 p->loc_BloomBlur_Parameters = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
3815 p->loc_ClientTime = qglGetUniformLocation(p->program, "ClientTime");
3816 p->loc_Color_Ambient = qglGetUniformLocation(p->program, "Color_Ambient");
3817 p->loc_Color_Diffuse = qglGetUniformLocation(p->program, "Color_Diffuse");
3818 p->loc_Color_Specular = qglGetUniformLocation(p->program, "Color_Specular");
3819 p->loc_Color_Glow = qglGetUniformLocation(p->program, "Color_Glow");
3820 p->loc_Color_Pants = qglGetUniformLocation(p->program, "Color_Pants");
3821 p->loc_Color_Shirt = qglGetUniformLocation(p->program, "Color_Shirt");
3822 p->loc_DeferredColor_Ambient = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
3823 p->loc_DeferredColor_Diffuse = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
3824 p->loc_DeferredColor_Specular = qglGetUniformLocation(p->program, "DeferredColor_Specular");
3825 p->loc_DeferredMod_Diffuse = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
3826 p->loc_DeferredMod_Specular = qglGetUniformLocation(p->program, "DeferredMod_Specular");
3827 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
3828 p->loc_EyePosition = qglGetUniformLocation(p->program, "EyePosition");
3829 p->loc_FogColor = qglGetUniformLocation(p->program, "FogColor");
3830 p->loc_FogHeightFade = qglGetUniformLocation(p->program, "FogHeightFade");
3831 p->loc_FogPlane = qglGetUniformLocation(p->program, "FogPlane");
3832 p->loc_FogPlaneViewDist = qglGetUniformLocation(p->program, "FogPlaneViewDist");
3833 p->loc_FogRangeRecip = qglGetUniformLocation(p->program, "FogRangeRecip");
3834 p->loc_LightColor = qglGetUniformLocation(p->program, "LightColor");
3835 p->loc_LightDir = qglGetUniformLocation(p->program, "LightDir");
3836 p->loc_LightPosition = qglGetUniformLocation(p->program, "LightPosition");
3837 p->loc_OffsetMapping_Scale = qglGetUniformLocation(p->program, "OffsetMapping_Scale");
3838 p->loc_PixelSize = qglGetUniformLocation(p->program, "PixelSize");
3839 p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor");
3840 p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor");
3841 p->loc_ReflectOffset = qglGetUniformLocation(p->program, "ReflectOffset");
3842 p->loc_RefractColor = qglGetUniformLocation(p->program, "RefractColor");
3843 p->loc_Saturation = qglGetUniformLocation(p->program, "Saturation");
3844 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
3845 p->loc_ScreenScaleRefractReflect = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
3846 p->loc_ScreenToDepth = qglGetUniformLocation(p->program, "ScreenToDepth");
3847 p->loc_ShadowMap_Parameters = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
3848 p->loc_ShadowMap_TextureScale = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
3849 p->loc_SpecularPower = qglGetUniformLocation(p->program, "SpecularPower");
3850 p->loc_UserVec1 = qglGetUniformLocation(p->program, "UserVec1");
3851 p->loc_UserVec2 = qglGetUniformLocation(p->program, "UserVec2");
3852 p->loc_UserVec3 = qglGetUniformLocation(p->program, "UserVec3");
3853 p->loc_UserVec4 = qglGetUniformLocation(p->program, "UserVec4");
3854 p->loc_ViewTintColor = qglGetUniformLocation(p->program, "ViewTintColor");
3855 p->loc_ViewToLight = qglGetUniformLocation(p->program, "ViewToLight");
3856 p->loc_ModelToLight = qglGetUniformLocation(p->program, "ModelToLight");
3857 p->loc_TexMatrix = qglGetUniformLocation(p->program, "TexMatrix");
3858 p->loc_BackgroundTexMatrix = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
3859 p->loc_ModelViewMatrix = qglGetUniformLocation(p->program, "ModelViewMatrix");
3860 p->loc_ModelViewProjectionMatrix = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
3861 p->loc_PixelToScreenTexCoord = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
3862 p->loc_ModelToReflectCube = qglGetUniformLocation(p->program, "ModelToReflectCube");
3863 p->loc_ShadowMapMatrix = qglGetUniformLocation(p->program, "ShadowMapMatrix");
3864 p->loc_BloomColorSubtract = qglGetUniformLocation(p->program, "BloomColorSubtract");
3865 p->loc_NormalmapScrollBlend = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
3866 // initialize the samplers to refer to the texture units we use
3867 p->tex_Texture_First = -1;
3868 p->tex_Texture_Second = -1;
3869 p->tex_Texture_GammaRamps = -1;
3870 p->tex_Texture_Normal = -1;
3871 p->tex_Texture_Color = -1;
3872 p->tex_Texture_Gloss = -1;
3873 p->tex_Texture_Glow = -1;
3874 p->tex_Texture_SecondaryNormal = -1;
3875 p->tex_Texture_SecondaryColor = -1;
3876 p->tex_Texture_SecondaryGloss = -1;
3877 p->tex_Texture_SecondaryGlow = -1;
3878 p->tex_Texture_Pants = -1;
3879 p->tex_Texture_Shirt = -1;
3880 p->tex_Texture_FogHeightTexture = -1;
3881 p->tex_Texture_FogMask = -1;
3882 p->tex_Texture_Lightmap = -1;
3883 p->tex_Texture_Deluxemap = -1;
3884 p->tex_Texture_Attenuation = -1;
3885 p->tex_Texture_Cube = -1;
3886 p->tex_Texture_Refraction = -1;
3887 p->tex_Texture_Reflection = -1;
3888 p->tex_Texture_ShadowMap2D = -1;
3889 p->tex_Texture_CubeProjection = -1;
3890 p->tex_Texture_ScreenDepth = -1;
3891 p->tex_Texture_ScreenNormalMap = -1;
3892 p->tex_Texture_ScreenDiffuse = -1;
3893 p->tex_Texture_ScreenSpecular = -1;
3894 p->tex_Texture_ReflectMask = -1;
3895 p->tex_Texture_ReflectCube = -1;
3897 if (p->loc_Texture_First >= 0) {p->tex_Texture_First = sampler;qglUniform1i(p->loc_Texture_First , sampler);sampler++;}
3898 if (p->loc_Texture_Second >= 0) {p->tex_Texture_Second = sampler;qglUniform1i(p->loc_Texture_Second , sampler);sampler++;}
3899 if (p->loc_Texture_GammaRamps >= 0) {p->tex_Texture_GammaRamps = sampler;qglUniform1i(p->loc_Texture_GammaRamps , sampler);sampler++;}
3900 if (p->loc_Texture_Normal >= 0) {p->tex_Texture_Normal = sampler;qglUniform1i(p->loc_Texture_Normal , sampler);sampler++;}
3901 if (p->loc_Texture_Color >= 0) {p->tex_Texture_Color = sampler;qglUniform1i(p->loc_Texture_Color , sampler);sampler++;}
3902 if (p->loc_Texture_Gloss >= 0) {p->tex_Texture_Gloss = sampler;qglUniform1i(p->loc_Texture_Gloss , sampler);sampler++;}
3903 if (p->loc_Texture_Glow >= 0) {p->tex_Texture_Glow = sampler;qglUniform1i(p->loc_Texture_Glow , sampler);sampler++;}
3904 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
3905 if (p->loc_Texture_SecondaryColor >= 0) {p->tex_Texture_SecondaryColor = sampler;qglUniform1i(p->loc_Texture_SecondaryColor , sampler);sampler++;}
3906 if (p->loc_Texture_SecondaryGloss >= 0) {p->tex_Texture_SecondaryGloss = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss , sampler);sampler++;}
3907 if (p->loc_Texture_SecondaryGlow >= 0) {p->tex_Texture_SecondaryGlow = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow , sampler);sampler++;}
3908 if (p->loc_Texture_Pants >= 0) {p->tex_Texture_Pants = sampler;qglUniform1i(p->loc_Texture_Pants , sampler);sampler++;}
3909 if (p->loc_Texture_Shirt >= 0) {p->tex_Texture_Shirt = sampler;qglUniform1i(p->loc_Texture_Shirt , sampler);sampler++;}
3910 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
3911 if (p->loc_Texture_FogMask >= 0) {p->tex_Texture_FogMask = sampler;qglUniform1i(p->loc_Texture_FogMask , sampler);sampler++;}
3912 if (p->loc_Texture_Lightmap >= 0) {p->tex_Texture_Lightmap = sampler;qglUniform1i(p->loc_Texture_Lightmap , sampler);sampler++;}
3913 if (p->loc_Texture_Deluxemap >= 0) {p->tex_Texture_Deluxemap = sampler;qglUniform1i(p->loc_Texture_Deluxemap , sampler);sampler++;}
3914 if (p->loc_Texture_Attenuation >= 0) {p->tex_Texture_Attenuation = sampler;qglUniform1i(p->loc_Texture_Attenuation , sampler);sampler++;}
3915 if (p->loc_Texture_Cube >= 0) {p->tex_Texture_Cube = sampler;qglUniform1i(p->loc_Texture_Cube , sampler);sampler++;}
3916 if (p->loc_Texture_Refraction >= 0) {p->tex_Texture_Refraction = sampler;qglUniform1i(p->loc_Texture_Refraction , sampler);sampler++;}
3917 if (p->loc_Texture_Reflection >= 0) {p->tex_Texture_Reflection = sampler;qglUniform1i(p->loc_Texture_Reflection , sampler);sampler++;}
3918 if (p->loc_Texture_ShadowMap2D >= 0) {p->tex_Texture_ShadowMap2D = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D , sampler);sampler++;}
3919 if (p->loc_Texture_CubeProjection >= 0) {p->tex_Texture_CubeProjection = sampler;qglUniform1i(p->loc_Texture_CubeProjection , sampler);sampler++;}
3920 if (p->loc_Texture_ScreenDepth >= 0) {p->tex_Texture_ScreenDepth = sampler;qglUniform1i(p->loc_Texture_ScreenDepth , sampler);sampler++;}
3921 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
3922 if (p->loc_Texture_ScreenDiffuse >= 0) {p->tex_Texture_ScreenDiffuse = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse , sampler);sampler++;}
3923 if (p->loc_Texture_ScreenSpecular >= 0) {p->tex_Texture_ScreenSpecular = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular , sampler);sampler++;}
3924 if (p->loc_Texture_ReflectMask >= 0) {p->tex_Texture_ReflectMask = sampler;qglUniform1i(p->loc_Texture_ReflectMask , sampler);sampler++;}
3925 if (p->loc_Texture_ReflectCube >= 0) {p->tex_Texture_ReflectCube = sampler;qglUniform1i(p->loc_Texture_ReflectCube , sampler);sampler++;}
3927 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
3930 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
3934 Mem_Free(vertexstring);
3936 Mem_Free(geometrystring);
3938 Mem_Free(fragmentstring);
3941 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3943 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3944 if (r_glsl_permutation != perm)
3946 r_glsl_permutation = perm;
3947 if (!r_glsl_permutation->program)
3949 if (!r_glsl_permutation->compiled)
3950 R_GLSL_CompilePermutation(perm, mode, permutation);
3951 if (!r_glsl_permutation->program)
3953 // remove features until we find a valid permutation
3955 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3957 // reduce i more quickly whenever it would not remove any bits
3958 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3959 if (!(permutation & j))
3962 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3963 if (!r_glsl_permutation->compiled)
3964 R_GLSL_CompilePermutation(perm, mode, permutation);
3965 if (r_glsl_permutation->program)
3968 if (i >= SHADERPERMUTATION_COUNT)
3970 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3971 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3972 qglUseProgram(0);CHECKGLERROR
3973 return; // no bit left to clear, entire mode is broken
3978 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
3980 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3981 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3982 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
3989 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
3990 extern D3DCAPS9 vid_d3d9caps;
3993 struct r_hlsl_permutation_s;
3994 typedef struct r_hlsl_permutation_s
3996 /// hash lookup data
3997 struct r_hlsl_permutation_s *hashnext;
3999 unsigned int permutation;
4001 /// indicates if we have tried compiling this permutation already
4003 /// NULL if compilation failed
4004 IDirect3DVertexShader9 *vertexshader;
4005 IDirect3DPixelShader9 *pixelshader;
4007 r_hlsl_permutation_t;
4009 typedef enum D3DVSREGISTER_e
4011 D3DVSREGISTER_TexMatrix = 0, // float4x4
4012 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
4013 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
4014 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
4015 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
4016 D3DVSREGISTER_ModelToLight = 20, // float4x4
4017 D3DVSREGISTER_EyePosition = 24,
4018 D3DVSREGISTER_FogPlane = 25,
4019 D3DVSREGISTER_LightDir = 26,
4020 D3DVSREGISTER_LightPosition = 27,
4024 typedef enum D3DPSREGISTER_e
4026 D3DPSREGISTER_Alpha = 0,
4027 D3DPSREGISTER_BloomBlur_Parameters = 1,
4028 D3DPSREGISTER_ClientTime = 2,
4029 D3DPSREGISTER_Color_Ambient = 3,
4030 D3DPSREGISTER_Color_Diffuse = 4,
4031 D3DPSREGISTER_Color_Specular = 5,
4032 D3DPSREGISTER_Color_Glow = 6,
4033 D3DPSREGISTER_Color_Pants = 7,
4034 D3DPSREGISTER_Color_Shirt = 8,
4035 D3DPSREGISTER_DeferredColor_Ambient = 9,
4036 D3DPSREGISTER_DeferredColor_Diffuse = 10,
4037 D3DPSREGISTER_DeferredColor_Specular = 11,
4038 D3DPSREGISTER_DeferredMod_Diffuse = 12,
4039 D3DPSREGISTER_DeferredMod_Specular = 13,
4040 D3DPSREGISTER_DistortScaleRefractReflect = 14,
4041 D3DPSREGISTER_EyePosition = 15, // unused
4042 D3DPSREGISTER_FogColor = 16,
4043 D3DPSREGISTER_FogHeightFade = 17,
4044 D3DPSREGISTER_FogPlane = 18,
4045 D3DPSREGISTER_FogPlaneViewDist = 19,
4046 D3DPSREGISTER_FogRangeRecip = 20,
4047 D3DPSREGISTER_LightColor = 21,
4048 D3DPSREGISTER_LightDir = 22, // unused
4049 D3DPSREGISTER_LightPosition = 23,
4050 D3DPSREGISTER_OffsetMapping_Scale = 24,
4051 D3DPSREGISTER_PixelSize = 25,
4052 D3DPSREGISTER_ReflectColor = 26,
4053 D3DPSREGISTER_ReflectFactor = 27,
4054 D3DPSREGISTER_ReflectOffset = 28,
4055 D3DPSREGISTER_RefractColor = 29,
4056 D3DPSREGISTER_Saturation = 30,
4057 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
4058 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
4059 D3DPSREGISTER_ScreenToDepth = 33,
4060 D3DPSREGISTER_ShadowMap_Parameters = 34,
4061 D3DPSREGISTER_ShadowMap_TextureScale = 35,
4062 D3DPSREGISTER_SpecularPower = 36,
4063 D3DPSREGISTER_UserVec1 = 37,
4064 D3DPSREGISTER_UserVec2 = 38,
4065 D3DPSREGISTER_UserVec3 = 39,
4066 D3DPSREGISTER_UserVec4 = 40,
4067 D3DPSREGISTER_ViewTintColor = 41,
4068 D3DPSREGISTER_PixelToScreenTexCoord = 42,
4069 D3DPSREGISTER_BloomColorSubtract = 43,
4070 D3DPSREGISTER_ViewToLight = 44, // float4x4
4071 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
4072 D3DPSREGISTER_NormalmapScrollBlend = 52,
4077 /// information about each possible shader permutation
4078 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4079 /// currently selected permutation
4080 r_hlsl_permutation_t *r_hlsl_permutation;
4081 /// storage for permutations linked in the hash table
4082 memexpandablearray_t r_hlsl_permutationarray;
4084 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
4086 //unsigned int hashdepth = 0;
4087 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4088 r_hlsl_permutation_t *p;
4089 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
4091 if (p->mode == mode && p->permutation == permutation)
4093 //if (hashdepth > 10)
4094 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4099 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
4101 p->permutation = permutation;
4102 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
4103 r_hlsl_permutationhash[mode][hashindex] = p;
4104 //if (hashdepth > 10)
4105 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4109 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
4112 if (!filename || !filename[0])
4114 if (!strcmp(filename, "hlsl/default.hlsl"))
4116 if (!hlslshaderstring)
4118 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4119 if (hlslshaderstring)
4120 Con_DPrintf("Loading shaders from file %s...\n", filename);
4122 hlslshaderstring = (char *)builtinhlslshaderstring;
4124 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
4125 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
4126 return shaderstring;
4128 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4131 if (printfromdisknotice)
4132 Con_DPrintf("from disk %s... ", filename);
4133 return shaderstring;
4135 return shaderstring;
4139 //#include <d3dx9shader.h>
4140 //#include <d3dx9mesh.h>
4142 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4144 DWORD *vsbin = NULL;
4145 DWORD *psbin = NULL;
4146 fs_offset_t vsbinsize;
4147 fs_offset_t psbinsize;
4148 // IDirect3DVertexShader9 *vs = NULL;
4149 // IDirect3DPixelShader9 *ps = NULL;
4150 ID3DXBuffer *vslog = NULL;
4151 ID3DXBuffer *vsbuffer = NULL;
4152 ID3DXConstantTable *vsconstanttable = NULL;
4153 ID3DXBuffer *pslog = NULL;
4154 ID3DXBuffer *psbuffer = NULL;
4155 ID3DXConstantTable *psconstanttable = NULL;
4158 char temp[MAX_INPUTLINE];
4159 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
4160 qboolean debugshader = gl_paranoid.integer != 0;
4161 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4162 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4165 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
4166 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
4168 if ((!vsbin && vertstring) || (!psbin && fragstring))
4170 const char* dllnames_d3dx9 [] =
4194 dllhandle_t d3dx9_dll = NULL;
4195 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4196 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
4197 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4198 dllfunction_t d3dx9_dllfuncs[] =
4200 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
4201 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
4202 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
4205 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
4207 DWORD shaderflags = 0;
4209 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
4210 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4211 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4212 if (vertstring && vertstring[0])
4216 // vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
4217 // FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
4218 FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
4219 vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4222 vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4225 vsbinsize = vsbuffer->GetBufferSize();
4226 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
4227 memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
4228 vsbuffer->Release();
4232 strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
4233 Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
4237 if (fragstring && fragstring[0])
4241 // psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
4242 // FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
4243 FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
4244 psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4247 psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4250 psbinsize = psbuffer->GetBufferSize();
4251 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
4252 memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
4253 psbuffer->Release();
4257 strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
4258 Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
4262 Sys_UnloadLibrary(&d3dx9_dll);
4265 Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
4269 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
4270 if (FAILED(vsresult))
4271 Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
4272 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
4273 if (FAILED(psresult))
4274 Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
4276 // free the shader data
4277 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4278 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4281 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
4284 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
4285 int vertstring_length = 0;
4286 int geomstring_length = 0;
4287 int fragstring_length = 0;
4289 char *vertexstring, *geometrystring, *fragmentstring;
4290 char *vertstring, *geomstring, *fragstring;
4291 char permutationname[256];
4292 char cachename[256];
4293 int vertstrings_count = 0;
4294 int geomstrings_count = 0;
4295 int fragstrings_count = 0;
4296 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4297 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4298 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4303 p->vertexshader = NULL;
4304 p->pixelshader = NULL;
4306 permutationname[0] = 0;
4308 vertexstring = R_HLSL_GetText(modeinfo->vertexfilename, true);
4309 geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
4310 fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
4312 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4313 strlcat(cachename, "hlsl/", sizeof(cachename));
4315 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
4316 vertstrings_count = 0;
4317 geomstrings_count = 0;
4318 fragstrings_count = 0;
4319 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
4320 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
4321 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
4323 // the first pretext is which type of shader to compile as
4324 // (later these will all be bound together as a program object)
4325 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4326 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4327 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4329 // the second pretext is the mode (for example a light source)
4330 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4331 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4332 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4333 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4334 strlcat(cachename, modeinfo->name, sizeof(cachename));
4336 // now add all the permutation pretexts
4337 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4339 if (permutation & (1<<i))
4341 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4342 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4343 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4344 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4345 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4349 // keep line numbers correct
4350 vertstrings_list[vertstrings_count++] = "\n";
4351 geomstrings_list[geomstrings_count++] = "\n";
4352 fragstrings_list[fragstrings_count++] = "\n";
4357 R_CompileShader_AddStaticParms(mode, permutation);
4358 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4359 vertstrings_count += shaderstaticparms_count;
4360 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4361 geomstrings_count += shaderstaticparms_count;
4362 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4363 fragstrings_count += shaderstaticparms_count;
4365 // replace spaces in the cachename with _ characters
4366 for (i = 0;cachename[i];i++)
4367 if (cachename[i] == ' ')
4370 // now append the shader text itself
4371 vertstrings_list[vertstrings_count++] = vertexstring;
4372 geomstrings_list[geomstrings_count++] = geometrystring;
4373 fragstrings_list[fragstrings_count++] = fragmentstring;
4375 // if any sources were NULL, clear the respective list
4377 vertstrings_count = 0;
4378 if (!geometrystring)
4379 geomstrings_count = 0;
4380 if (!fragmentstring)
4381 fragstrings_count = 0;
4383 vertstring_length = 0;
4384 for (i = 0;i < vertstrings_count;i++)
4385 vertstring_length += strlen(vertstrings_list[i]);
4386 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
4387 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4388 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4390 geomstring_length = 0;
4391 for (i = 0;i < geomstrings_count;i++)
4392 geomstring_length += strlen(geomstrings_list[i]);
4393 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
4394 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4395 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4397 fragstring_length = 0;
4398 for (i = 0;i < fragstrings_count;i++)
4399 fragstring_length += strlen(fragstrings_list[i]);
4400 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
4401 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4402 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4404 // try to load the cached shader, or generate one
4405 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
4407 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
4408 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
4410 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
4414 Mem_Free(vertstring);
4416 Mem_Free(geomstring);
4418 Mem_Free(fragstring);
4420 Mem_Free(vertexstring);
4422 Mem_Free(geometrystring);
4424 Mem_Free(fragmentstring);
4427 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
4428 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
4429 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);}
4430 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);}
4431 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);}
4432 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);}
4434 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
4435 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
4436 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);}
4437 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);}
4438 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);}
4439 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);}
4441 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
4443 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
4444 if (r_hlsl_permutation != perm)
4446 r_hlsl_permutation = perm;
4447 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4449 if (!r_hlsl_permutation->compiled)
4450 R_HLSL_CompilePermutation(perm, mode, permutation);
4451 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4453 // remove features until we find a valid permutation
4455 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4457 // reduce i more quickly whenever it would not remove any bits
4458 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4459 if (!(permutation & j))
4462 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4463 if (!r_hlsl_permutation->compiled)
4464 R_HLSL_CompilePermutation(perm, mode, permutation);
4465 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
4468 if (i >= SHADERPERMUTATION_COUNT)
4470 //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4471 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4472 return; // no bit left to clear, entire mode is broken
4476 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
4477 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
4479 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
4480 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
4481 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
4485 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
4487 DPSOFTRAST_SetShader(mode, permutation);
4488 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
4489 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
4490 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
4493 void R_GLSL_Restart_f(void)
4495 unsigned int i, limit;
4496 if (glslshaderstring && glslshaderstring != builtinshaderstring)
4497 Mem_Free(glslshaderstring);
4498 glslshaderstring = NULL;
4499 if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
4500 Mem_Free(hlslshaderstring);
4501 hlslshaderstring = NULL;
4502 switch(vid.renderpath)
4504 case RENDERPATH_D3D9:
4507 r_hlsl_permutation_t *p;
4508 r_hlsl_permutation = NULL;
4509 limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
4510 for (i = 0;i < limit;i++)
4512 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
4514 if (p->vertexshader)
4515 IDirect3DVertexShader9_Release(p->vertexshader);
4517 IDirect3DPixelShader9_Release(p->pixelshader);
4518 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
4521 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4525 case RENDERPATH_D3D10:
4526 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4528 case RENDERPATH_D3D11:
4529 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4531 case RENDERPATH_GL20:
4532 case RENDERPATH_GLES2:
4534 r_glsl_permutation_t *p;
4535 r_glsl_permutation = NULL;
4536 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
4537 for (i = 0;i < limit;i++)
4539 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
4541 GL_Backend_FreeProgram(p->program);
4542 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
4545 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4548 case RENDERPATH_GL13:
4549 case RENDERPATH_GL11:
4551 case RENDERPATH_SOFT:
4556 void R_GLSL_DumpShader_f(void)
4561 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
4564 FS_Print(file, "/* The engine may define the following macros:\n");
4565 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4566 for (i = 0;i < SHADERMODE_COUNT;i++)
4567 FS_Print(file, glslshadermodeinfo[i].pretext);
4568 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4569 FS_Print(file, shaderpermutationinfo[i].pretext);
4570 FS_Print(file, "*/\n");
4571 FS_Print(file, builtinshaderstring);
4573 Con_Printf("glsl/default.glsl written\n");
4576 Con_Printf("failed to write to glsl/default.glsl\n");
4578 file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
4581 FS_Print(file, "/* The engine may define the following macros:\n");
4582 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4583 for (i = 0;i < SHADERMODE_COUNT;i++)
4584 FS_Print(file, hlslshadermodeinfo[i].pretext);
4585 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4586 FS_Print(file, shaderpermutationinfo[i].pretext);
4587 FS_Print(file, "*/\n");
4588 FS_Print(file, builtinhlslshaderstring);
4590 Con_Printf("hlsl/default.hlsl written\n");
4593 Con_Printf("failed to write to hlsl/default.hlsl\n");
4596 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
4599 texturemode = GL_MODULATE;
4600 switch (vid.renderpath)
4602 case RENDERPATH_D3D9:
4604 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))));
4605 R_Mesh_TexBind(GL20TU_FIRST , first );
4606 R_Mesh_TexBind(GL20TU_SECOND, second);
4609 case RENDERPATH_D3D10:
4610 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4612 case RENDERPATH_D3D11:
4613 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4615 case RENDERPATH_GL20:
4616 case RENDERPATH_GLES2:
4617 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))));
4618 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
4619 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
4621 case RENDERPATH_GL13:
4622 R_Mesh_TexBind(0, first );
4623 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
4624 R_Mesh_TexBind(1, second);
4626 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
4628 case RENDERPATH_GL11:
4629 R_Mesh_TexBind(0, first );
4631 case RENDERPATH_SOFT:
4632 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))));
4633 R_Mesh_TexBind(GL20TU_FIRST , first );
4634 R_Mesh_TexBind(GL20TU_SECOND, second);
4639 void R_SetupShader_DepthOrShadow(void)
4641 switch (vid.renderpath)
4643 case RENDERPATH_D3D9:
4645 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4648 case RENDERPATH_D3D10:
4649 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4651 case RENDERPATH_D3D11:
4652 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4654 case RENDERPATH_GL20:
4655 case RENDERPATH_GLES2:
4656 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4658 case RENDERPATH_GL13:
4659 R_Mesh_TexBind(0, 0);
4660 R_Mesh_TexBind(1, 0);
4662 case RENDERPATH_GL11:
4663 R_Mesh_TexBind(0, 0);
4665 case RENDERPATH_SOFT:
4666 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
4671 void R_SetupShader_ShowDepth(void)
4673 switch (vid.renderpath)
4675 case RENDERPATH_D3D9:
4677 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
4680 case RENDERPATH_D3D10:
4681 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4683 case RENDERPATH_D3D11:
4684 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4686 case RENDERPATH_GL20:
4687 case RENDERPATH_GLES2:
4688 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
4690 case RENDERPATH_GL13:
4692 case RENDERPATH_GL11:
4694 case RENDERPATH_SOFT:
4695 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
4700 extern qboolean r_shadow_usingdeferredprepass;
4701 extern cvar_t r_shadow_deferred_8bitrange;
4702 extern rtexture_t *r_shadow_attenuationgradienttexture;
4703 extern rtexture_t *r_shadow_attenuation2dtexture;
4704 extern rtexture_t *r_shadow_attenuation3dtexture;
4705 extern qboolean r_shadow_usingshadowmap2d;
4706 extern qboolean r_shadow_usingshadowmaportho;
4707 extern float r_shadow_shadowmap_texturescale[2];
4708 extern float r_shadow_shadowmap_parameters[4];
4709 extern qboolean r_shadow_shadowmapvsdct;
4710 extern qboolean r_shadow_shadowmapsampler;
4711 extern int r_shadow_shadowmappcf;
4712 extern rtexture_t *r_shadow_shadowmap2dtexture;
4713 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
4714 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
4715 extern matrix4x4_t r_shadow_shadowmapmatrix;
4716 extern int r_shadow_shadowmaplod; // changes for each light based on distance
4717 extern int r_shadow_prepass_width;
4718 extern int r_shadow_prepass_height;
4719 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
4720 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
4721 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
4722 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
4723 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
4724 static qboolean R_BlendFuncAllowsColormod(int src, int dst)
4726 // a blendfunc allows colormod if:
4727 // a) it can never keep the destination pixel invariant, or
4728 // b) it can keep the destination pixel invariant, and still can do so if colormodded
4729 // this is to prevent unintended side effects from colormod
4732 // IF there is a (s, sa) for which for all (d, da),
4733 // s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
4734 // THEN, for this (s, sa) and all (colormod, d, da):
4735 // s*colormod * src(s*colormod, d, sa, da) + d * dst(s*colormod, d, sa, da) == d
4736 // OBVIOUSLY, this means that
4737 // s*colormod * src(s*colormod, d, sa, da) = 0
4738 // dst(s*colormod, d, sa, da) = 1
4740 // note: not caring about GL_SRC_ALPHA_SATURATE and following here, these are unused in DP code
4742 // main condition to leave dst color invariant:
4743 // s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
4745 // s * 0 + d * dst(s, d, sa, da) == d
4746 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4747 // => colormod is a problem for GL_SRC_COLOR only
4749 // s + d * dst(s, d, sa, da) == d
4751 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4752 // => colormod is never problematic for these
4753 // src == GL_SRC_COLOR:
4754 // s*s + d * dst(s, d, sa, da) == d
4756 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4757 // => colormod is never problematic for these
4758 // src == GL_ONE_MINUS_SRC_COLOR:
4759 // s*(1-s) + d * dst(s, d, sa, da) == d
4760 // => s == 0 or s == 1
4761 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4762 // => colormod is a problem for GL_SRC_COLOR only
4763 // src == GL_DST_COLOR
4764 // s*d + d * dst(s, d, sa, da) == d
4766 // => dst == GL_ZERO/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4767 // => colormod is always a problem
4770 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4771 // => colormod is never problematic for these
4772 // => BUT, we do not know s! We must assume it is problematic
4773 // then... except in GL_ONE case, where we know all invariant
4775 // src == GL_ONE_MINUS_DST_COLOR
4776 // s*(1-d) + d * dst(s, d, sa, da) == d
4777 // => s == 0 (1-d is impossible to handle for our desired result)
4778 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4779 // => colormod is never problematic for these
4780 // src == GL_SRC_ALPHA
4781 // s*sa + d * dst(s, d, sa, da) == d
4782 // => s == 0, or sa == 0
4783 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4784 // => colormod breaks in the case GL_SRC_COLOR only
4785 // src == GL_ONE_MINUS_SRC_ALPHA
4786 // s*(1-sa) + d * dst(s, d, sa, da) == d
4787 // => s == 0, or sa == 1
4788 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4789 // => colormod breaks in the case GL_SRC_COLOR only
4790 // src == GL_DST_ALPHA
4791 // s*da + d * dst(s, d, sa, da) == d
4793 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4794 // => colormod is never problematic for these
4799 case GL_ONE_MINUS_SRC_COLOR:
4801 case GL_ONE_MINUS_SRC_ALPHA:
4802 if(dst == GL_SRC_COLOR)
4807 case GL_ONE_MINUS_DST_COLOR:
4809 case GL_ONE_MINUS_DST_ALPHA:
4819 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)
4821 // select a permutation of the lighting shader appropriate to this
4822 // combination of texture, entity, light source, and fogging, only use the
4823 // minimum features necessary to avoid wasting rendering time in the
4824 // fragment shader on features that are not being used
4825 unsigned int permutation = 0;
4826 unsigned int mode = 0;
4827 qboolean allow_colormod;
4828 static float dummy_colormod[3] = {1, 1, 1};
4829 float *colormod = rsurface.colormod;
4831 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
4832 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4833 permutation |= SHADERPERMUTATION_ALPHAKILL;
4834 if (rsurfacepass == RSURFPASS_BACKGROUND)
4836 // distorted background
4837 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
4839 mode = SHADERMODE_WATER;
4840 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
4841 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND;
4842 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
4844 // this is the right thing to do for wateralpha
4845 GL_BlendFunc(GL_ONE, GL_ZERO);
4846 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
4850 // this is the right thing to do for entity alpha
4851 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4852 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4855 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
4857 mode = SHADERMODE_REFRACTION;
4858 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4859 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4863 mode = SHADERMODE_GENERIC;
4864 permutation |= SHADERPERMUTATION_DIFFUSE;
4865 GL_BlendFunc(GL_ONE, GL_ZERO);
4866 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
4869 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
4871 if (r_glsl_offsetmapping.integer)
4873 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4874 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4875 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4876 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4877 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4879 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4880 if (r_glsl_offsetmapping_reliefmapping.integer)
4881 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4884 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4885 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4886 // normalmap (deferred prepass), may use alpha test on diffuse
4887 mode = SHADERMODE_DEFERREDGEOMETRY;
4888 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4889 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4890 GL_BlendFunc(GL_ONE, GL_ZERO);
4891 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
4893 else if (rsurfacepass == RSURFPASS_RTLIGHT)
4895 if (r_glsl_offsetmapping.integer)
4897 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4898 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4899 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4900 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4901 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4903 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4904 if (r_glsl_offsetmapping_reliefmapping.integer)
4905 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4908 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4909 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4911 mode = SHADERMODE_LIGHTSOURCE;
4912 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4913 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4914 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
4915 permutation |= SHADERPERMUTATION_CUBEFILTER;
4916 if (diffusescale > 0)
4917 permutation |= SHADERPERMUTATION_DIFFUSE;
4918 if (specularscale > 0)
4919 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4920 if (r_refdef.fogenabled)
4921 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
4922 if (rsurface.texture->colormapping)
4923 permutation |= SHADERPERMUTATION_COLORMAPPING;
4924 if (r_shadow_usingshadowmap2d)
4926 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4927 if(r_shadow_shadowmapvsdct)
4928 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4930 if (r_shadow_shadowmapsampler)
4931 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4932 if (r_shadow_shadowmappcf > 1)
4933 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4934 else if (r_shadow_shadowmappcf)
4935 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4937 if (rsurface.texture->reflectmasktexture)
4938 permutation |= SHADERPERMUTATION_REFLECTCUBE;
4939 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4940 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE);
4942 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4944 if (r_glsl_offsetmapping.integer)
4946 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4947 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4948 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4949 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4950 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4952 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4953 if (r_glsl_offsetmapping_reliefmapping.integer)
4954 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4957 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4958 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4959 // unshaded geometry (fullbright or ambient model lighting)
4960 mode = SHADERMODE_FLATCOLOR;
4961 ambientscale = diffusescale = specularscale = 0;
4962 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4963 permutation |= SHADERPERMUTATION_GLOW;
4964 if (r_refdef.fogenabled)
4965 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
4966 if (rsurface.texture->colormapping)
4967 permutation |= SHADERPERMUTATION_COLORMAPPING;
4968 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4970 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4971 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4973 if (r_shadow_shadowmapsampler)
4974 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4975 if (r_shadow_shadowmappcf > 1)
4976 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4977 else if (r_shadow_shadowmappcf)
4978 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4980 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4981 permutation |= SHADERPERMUTATION_REFLECTION;
4982 if (rsurface.texture->reflectmasktexture)
4983 permutation |= SHADERPERMUTATION_REFLECTCUBE;
4984 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4985 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4987 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
4989 if (r_glsl_offsetmapping.integer)
4991 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4992 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4993 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4994 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4995 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4997 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4998 if (r_glsl_offsetmapping_reliefmapping.integer)
4999 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5002 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5003 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5004 // directional model lighting
5005 mode = SHADERMODE_LIGHTDIRECTION;
5006 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5007 permutation |= SHADERPERMUTATION_GLOW;
5008 permutation |= SHADERPERMUTATION_DIFFUSE;
5009 if (specularscale > 0)
5010 permutation |= SHADERPERMUTATION_SPECULAR;
5011 if (r_refdef.fogenabled)
5012 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5013 if (rsurface.texture->colormapping)
5014 permutation |= SHADERPERMUTATION_COLORMAPPING;
5015 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5017 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5018 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5020 if (r_shadow_shadowmapsampler)
5021 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5022 if (r_shadow_shadowmappcf > 1)
5023 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5024 else if (r_shadow_shadowmappcf)
5025 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5027 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5028 permutation |= SHADERPERMUTATION_REFLECTION;
5029 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5030 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5031 if (rsurface.texture->reflectmasktexture)
5032 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5033 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5034 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5036 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5038 if (r_glsl_offsetmapping.integer)
5040 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5041 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5042 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5043 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5044 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5046 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5047 if (r_glsl_offsetmapping_reliefmapping.integer)
5048 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5051 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5052 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5053 // ambient model lighting
5054 mode = SHADERMODE_LIGHTDIRECTION;
5055 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5056 permutation |= SHADERPERMUTATION_GLOW;
5057 if (r_refdef.fogenabled)
5058 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5059 if (rsurface.texture->colormapping)
5060 permutation |= SHADERPERMUTATION_COLORMAPPING;
5061 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5063 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5064 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5066 if (r_shadow_shadowmapsampler)
5067 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5068 if (r_shadow_shadowmappcf > 1)
5069 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5070 else if (r_shadow_shadowmappcf)
5071 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5073 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5074 permutation |= SHADERPERMUTATION_REFLECTION;
5075 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5076 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5077 if (rsurface.texture->reflectmasktexture)
5078 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5079 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5080 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5084 if (r_glsl_offsetmapping.integer)
5086 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5087 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5088 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5089 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5090 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5092 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5093 if (r_glsl_offsetmapping_reliefmapping.integer)
5094 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5097 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5098 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5100 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5101 permutation |= SHADERPERMUTATION_GLOW;
5102 if (r_refdef.fogenabled)
5103 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5104 if (rsurface.texture->colormapping)
5105 permutation |= SHADERPERMUTATION_COLORMAPPING;
5106 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5108 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5109 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5111 if (r_shadow_shadowmapsampler)
5112 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5113 if (r_shadow_shadowmappcf > 1)
5114 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5115 else if (r_shadow_shadowmappcf)
5116 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5118 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5119 permutation |= SHADERPERMUTATION_REFLECTION;
5120 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5121 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5122 if (rsurface.texture->reflectmasktexture)
5123 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5124 if (FAKELIGHT_ENABLED)
5126 // fake lightmapping (q1bsp, q3bsp, fullbright map)
5127 mode = SHADERMODE_FAKELIGHT;
5128 permutation |= SHADERPERMUTATION_DIFFUSE;
5129 if (specularscale > 0)
5130 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5132 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
5134 // deluxemapping (light direction texture)
5135 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
5136 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
5138 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5139 permutation |= SHADERPERMUTATION_DIFFUSE;
5140 if (specularscale > 0)
5141 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5143 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
5145 // fake deluxemapping (uniform light direction in tangentspace)
5146 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5147 permutation |= SHADERPERMUTATION_DIFFUSE;
5148 if (specularscale > 0)
5149 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5151 else if (rsurface.uselightmaptexture)
5153 // ordinary lightmapping (q1bsp, q3bsp)
5154 mode = SHADERMODE_LIGHTMAP;
5158 // ordinary vertex coloring (q3bsp)
5159 mode = SHADERMODE_VERTEXCOLOR;
5161 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5162 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5165 colormod = dummy_colormod;
5166 switch(vid.renderpath)
5168 case RENDERPATH_D3D9:
5170 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);
5171 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5172 R_SetupShader_SetPermutationHLSL(mode, permutation);
5173 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
5174 if (mode == SHADERMODE_LIGHTSOURCE)
5176 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
5177 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5181 if (mode == SHADERMODE_LIGHTDIRECTION)
5183 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5186 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
5187 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
5188 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
5189 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5190 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5192 if (mode == SHADERMODE_LIGHTSOURCE)
5194 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5195 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5196 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5197 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5198 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5200 // additive passes are only darkened by fog, not tinted
5201 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5202 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5206 if (mode == SHADERMODE_FLATCOLOR)
5208 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5210 else if (mode == SHADERMODE_LIGHTDIRECTION)
5212 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]);
5213 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5214 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);
5215 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);
5216 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5217 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
5218 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5222 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5223 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5224 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);
5225 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);
5226 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5228 // additive passes are only darkened by fog, not tinted
5229 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5230 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5232 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5233 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);
5234 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5235 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5236 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5237 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5238 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5239 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
5240 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5241 if (mode == SHADERMODE_WATER)
5242 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
5244 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5245 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5246 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5247 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));
5248 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5249 if (rsurface.texture->pantstexture)
5250 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5252 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
5253 if (rsurface.texture->shirttexture)
5254 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5256 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
5257 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5258 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
5259 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
5260 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
5261 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
5262 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5263 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5265 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
5266 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
5267 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
5268 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
5269 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
5270 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
5271 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
5272 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
5273 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
5274 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
5275 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
5276 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5277 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
5278 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
5279 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5280 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5281 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
5282 if (rsurfacepass == RSURFPASS_BACKGROUND)
5284 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5285 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5286 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5290 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5292 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
5293 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
5294 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
5295 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
5296 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5298 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
5299 if (rsurface.rtlight)
5301 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
5302 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
5307 case RENDERPATH_D3D10:
5308 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5310 case RENDERPATH_D3D11:
5311 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5313 case RENDERPATH_GL20:
5314 case RENDERPATH_GLES2:
5315 if (!vid.useinterleavedarrays)
5317 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);
5318 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5319 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5320 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5321 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5322 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5323 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5324 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5328 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);
5329 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5331 R_SetupShader_SetPermutationGLSL(mode, permutation);
5332 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
5333 if (mode == SHADERMODE_LIGHTSOURCE)
5335 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
5336 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5337 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5338 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5339 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5340 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);
5342 // additive passes are only darkened by fog, not tinted
5343 if (r_glsl_permutation->loc_FogColor >= 0)
5344 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5345 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5349 if (mode == SHADERMODE_FLATCOLOR)
5351 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5353 else if (mode == SHADERMODE_LIGHTDIRECTION)
5355 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]);
5356 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]);
5357 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);
5358 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);
5359 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);
5360 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]);
5361 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]);
5365 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]);
5366 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]);
5367 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);
5368 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);
5369 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);
5371 // additive passes are only darkened by fog, not tinted
5372 if (r_glsl_permutation->loc_FogColor >= 0)
5374 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5375 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5377 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5379 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);
5380 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]);
5381 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]);
5382 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]);
5383 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]);
5384 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5385 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
5386 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5387 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]);
5389 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
5390 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
5391 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
5392 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]);
5393 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]);
5395 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5396 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));
5397 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5398 if (r_glsl_permutation->loc_Color_Pants >= 0)
5400 if (rsurface.texture->pantstexture)
5401 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5403 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
5405 if (r_glsl_permutation->loc_Color_Shirt >= 0)
5407 if (rsurface.texture->shirttexture)
5408 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5410 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
5412 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]);
5413 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
5414 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
5415 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
5416 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5417 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]);
5418 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5420 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
5421 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
5422 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
5423 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
5424 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
5425 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
5426 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
5427 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
5428 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
5429 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
5430 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
5431 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
5432 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
5433 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
5434 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);
5435 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
5436 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
5437 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5438 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5439 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
5440 if (rsurfacepass == RSURFPASS_BACKGROUND)
5442 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);
5443 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);
5444 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);
5448 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);
5450 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
5451 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
5452 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
5453 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
5454 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5456 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture );
5457 if (rsurface.rtlight)
5459 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
5460 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
5465 case RENDERPATH_GL13:
5466 case RENDERPATH_GL11:
5468 case RENDERPATH_SOFT:
5469 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);
5470 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
5471 R_SetupShader_SetPermutationSoft(mode, permutation);
5472 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
5473 if (mode == SHADERMODE_LIGHTSOURCE)
5475 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
5476 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5477 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5478 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5479 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5480 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5482 // additive passes are only darkened by fog, not tinted
5483 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
5484 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5488 if (mode == SHADERMODE_FLATCOLOR)
5490 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5492 else if (mode == SHADERMODE_LIGHTDIRECTION)
5494 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]);
5495 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5496 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);
5497 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);
5498 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5499 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]);
5500 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5504 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5505 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5506 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);
5507 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);
5508 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5510 // additive passes are only darkened by fog, not tinted
5511 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5512 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
5514 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5515 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);
5516 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5517 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5518 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]);
5519 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]);
5520 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5521 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
5522 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5523 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
5525 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
5526 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
5527 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
5528 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5529 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]);
5531 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5532 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));
5533 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5534 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
5536 if (rsurface.texture->pantstexture)
5537 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5539 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
5541 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
5543 if (rsurface.texture->shirttexture)
5544 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5546 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
5548 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5549 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
5550 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
5551 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
5552 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5553 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5554 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5556 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
5557 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
5558 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
5559 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
5560 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
5561 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
5562 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
5563 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
5564 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
5565 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
5566 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
5567 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5568 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
5569 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
5570 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5571 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5572 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
5573 if (rsurfacepass == RSURFPASS_BACKGROUND)
5575 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5576 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5577 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5581 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5583 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
5584 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
5585 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
5586 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
5587 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5589 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
5590 if (rsurface.rtlight)
5592 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
5593 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
5600 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
5602 // select a permutation of the lighting shader appropriate to this
5603 // combination of texture, entity, light source, and fogging, only use the
5604 // minimum features necessary to avoid wasting rendering time in the
5605 // fragment shader on features that are not being used
5606 unsigned int permutation = 0;
5607 unsigned int mode = 0;
5608 const float *lightcolorbase = rtlight->currentcolor;
5609 float ambientscale = rtlight->ambientscale;
5610 float diffusescale = rtlight->diffusescale;
5611 float specularscale = rtlight->specularscale;
5612 // this is the location of the light in view space
5613 vec3_t viewlightorigin;
5614 // this transforms from view space (camera) to light space (cubemap)
5615 matrix4x4_t viewtolight;
5616 matrix4x4_t lighttoview;
5617 float viewtolight16f[16];
5618 float range = 1.0f / r_shadow_deferred_8bitrange.value;
5620 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
5621 if (rtlight->currentcubemap != r_texture_whitecube)
5622 permutation |= SHADERPERMUTATION_CUBEFILTER;
5623 if (diffusescale > 0)
5624 permutation |= SHADERPERMUTATION_DIFFUSE;
5625 if (specularscale > 0)
5626 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5627 if (r_shadow_usingshadowmap2d)
5629 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5630 if (r_shadow_shadowmapvsdct)
5631 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5633 if (r_shadow_shadowmapsampler)
5634 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5635 if (r_shadow_shadowmappcf > 1)
5636 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5637 else if (r_shadow_shadowmappcf)
5638 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5640 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
5641 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
5642 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
5643 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
5644 switch(vid.renderpath)
5646 case RENDERPATH_D3D9:
5648 R_SetupShader_SetPermutationHLSL(mode, permutation);
5649 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
5650 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
5651 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
5652 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
5653 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
5654 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5655 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5656 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5657 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5658 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5660 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
5661 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthcolortexture );
5662 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
5663 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
5664 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dcolortexture );
5665 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
5668 case RENDERPATH_D3D10:
5669 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5671 case RENDERPATH_D3D11:
5672 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5674 case RENDERPATH_GL20:
5675 case RENDERPATH_GLES2:
5676 R_SetupShader_SetPermutationGLSL(mode, permutation);
5677 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
5678 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
5679 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);
5680 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);
5681 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);
5682 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]);
5683 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]);
5684 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));
5685 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]);
5686 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
5688 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
5689 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
5690 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
5691 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
5692 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );
5693 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
5695 case RENDERPATH_GL13:
5696 case RENDERPATH_GL11:
5698 case RENDERPATH_SOFT:
5699 R_SetupShader_SetPermutationGLSL(mode, permutation);
5700 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
5701 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
5702 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
5703 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
5704 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
5705 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5706 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]);
5707 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));
5708 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5709 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5711 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
5712 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
5713 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
5714 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
5715 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
5716 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
5721 #define SKINFRAME_HASH 1024
5725 int loadsequence; // incremented each level change
5726 memexpandablearray_t array;
5727 skinframe_t *hash[SKINFRAME_HASH];
5730 r_skinframe_t r_skinframe;
5732 void R_SkinFrame_PrepareForPurge(void)
5734 r_skinframe.loadsequence++;
5735 // wrap it without hitting zero
5736 if (r_skinframe.loadsequence >= 200)
5737 r_skinframe.loadsequence = 1;
5740 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
5744 // mark the skinframe as used for the purging code
5745 skinframe->loadsequence = r_skinframe.loadsequence;
5748 void R_SkinFrame_Purge(void)
5752 for (i = 0;i < SKINFRAME_HASH;i++)
5754 for (s = r_skinframe.hash[i];s;s = s->next)
5756 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
5758 if (s->merged == s->base)
5760 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
5761 R_PurgeTexture(s->stain );s->stain = NULL;
5762 R_PurgeTexture(s->merged);s->merged = NULL;
5763 R_PurgeTexture(s->base );s->base = NULL;
5764 R_PurgeTexture(s->pants );s->pants = NULL;
5765 R_PurgeTexture(s->shirt );s->shirt = NULL;
5766 R_PurgeTexture(s->nmap );s->nmap = NULL;
5767 R_PurgeTexture(s->gloss );s->gloss = NULL;
5768 R_PurgeTexture(s->glow );s->glow = NULL;
5769 R_PurgeTexture(s->fog );s->fog = NULL;
5770 R_PurgeTexture(s->reflect);s->reflect = NULL;
5771 s->loadsequence = 0;
5777 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
5779 char basename[MAX_QPATH];
5781 Image_StripImageExtension(name, basename, sizeof(basename));
5783 if( last == NULL ) {
5785 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5786 item = r_skinframe.hash[hashindex];
5791 // linearly search through the hash bucket
5792 for( ; item ; item = item->next ) {
5793 if( !strcmp( item->basename, basename ) ) {
5800 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
5804 char basename[MAX_QPATH];
5806 Image_StripImageExtension(name, basename, sizeof(basename));
5808 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5809 for (item = r_skinframe.hash[hashindex];item;item = item->next)
5810 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
5814 rtexture_t *dyntexture;
5815 // check whether its a dynamic texture
5816 dyntexture = CL_GetDynTexture( basename );
5817 if (!add && !dyntexture)
5819 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
5820 memset(item, 0, sizeof(*item));
5821 strlcpy(item->basename, basename, sizeof(item->basename));
5822 item->base = dyntexture; // either NULL or dyntexture handle
5823 item->textureflags = textureflags;
5824 item->comparewidth = comparewidth;
5825 item->compareheight = compareheight;
5826 item->comparecrc = comparecrc;
5827 item->next = r_skinframe.hash[hashindex];
5828 r_skinframe.hash[hashindex] = item;
5830 else if( item->base == NULL )
5832 rtexture_t *dyntexture;
5833 // check whether its a dynamic texture
5834 // 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]
5835 dyntexture = CL_GetDynTexture( basename );
5836 item->base = dyntexture; // either NULL or dyntexture handle
5839 R_SkinFrame_MarkUsed(item);
5843 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
5845 unsigned long long avgcolor[5], wsum; \
5853 for(pix = 0; pix < cnt; ++pix) \
5856 for(comp = 0; comp < 3; ++comp) \
5858 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
5861 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5863 for(comp = 0; comp < 3; ++comp) \
5864 avgcolor[comp] += getpixel * w; \
5867 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5868 avgcolor[4] += getpixel; \
5870 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
5872 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
5873 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
5874 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
5875 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
5878 extern cvar_t gl_picmip;
5879 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
5882 unsigned char *pixels;
5883 unsigned char *bumppixels;
5884 unsigned char *basepixels = NULL;
5885 int basepixels_width = 0;
5886 int basepixels_height = 0;
5887 skinframe_t *skinframe;
5888 rtexture_t *ddsbase = NULL;
5889 qboolean ddshasalpha = false;
5890 float ddsavgcolor[4];
5891 char basename[MAX_QPATH];
5892 int miplevel = R_PicmipForFlags(textureflags);
5893 int savemiplevel = miplevel;
5896 if (cls.state == ca_dedicated)
5899 // return an existing skinframe if already loaded
5900 // if loading of the first image fails, don't make a new skinframe as it
5901 // would cause all future lookups of this to be missing
5902 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5903 if (skinframe && skinframe->base)
5906 Image_StripImageExtension(name, basename, sizeof(basename));
5908 // check for DDS texture file first
5909 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
5911 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
5912 if (basepixels == NULL)
5916 // FIXME handle miplevel
5918 if (developer_loading.integer)
5919 Con_Printf("loading skin \"%s\"\n", name);
5921 // we've got some pixels to store, so really allocate this new texture now
5923 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
5924 skinframe->stain = NULL;
5925 skinframe->merged = NULL;
5926 skinframe->base = NULL;
5927 skinframe->pants = NULL;
5928 skinframe->shirt = NULL;
5929 skinframe->nmap = NULL;
5930 skinframe->gloss = NULL;
5931 skinframe->glow = NULL;
5932 skinframe->fog = NULL;
5933 skinframe->reflect = NULL;
5934 skinframe->hasalpha = false;
5938 skinframe->base = ddsbase;
5939 skinframe->hasalpha = ddshasalpha;
5940 VectorCopy(ddsavgcolor, skinframe->avgcolor);
5941 if (r_loadfog && skinframe->hasalpha)
5942 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
5943 //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]);
5947 basepixels_width = image_width;
5948 basepixels_height = image_height;
5949 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);
5950 if (textureflags & TEXF_ALPHA)
5952 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
5954 if (basepixels[j] < 255)
5956 skinframe->hasalpha = true;
5960 if (r_loadfog && skinframe->hasalpha)
5962 // has transparent pixels
5963 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5964 for (j = 0;j < image_width * image_height * 4;j += 4)
5969 pixels[j+3] = basepixels[j+3];
5971 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);
5975 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
5976 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
5977 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
5978 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
5979 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
5980 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
5985 mymiplevel = savemiplevel;
5986 if (r_loadnormalmap)
5987 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);
5988 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
5990 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
5991 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
5992 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
5993 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
5996 // _norm is the name used by tenebrae and has been adopted as standard
5997 if (r_loadnormalmap && skinframe->nmap == NULL)
5999 mymiplevel = savemiplevel;
6000 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6002 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);
6006 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6008 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6009 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
6010 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);
6012 Mem_Free(bumppixels);
6014 else if (r_shadow_bumpscale_basetexture.value > 0)
6016 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
6017 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
6018 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);
6021 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
6022 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
6025 // _luma is supported only for tenebrae compatibility
6026 // _glow is the preferred name
6027 mymiplevel = savemiplevel;
6028 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))))
6030 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);
6031 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
6032 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
6033 Mem_Free(pixels);pixels = NULL;
6036 mymiplevel = savemiplevel;
6037 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6039 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);
6040 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
6041 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
6046 mymiplevel = savemiplevel;
6047 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6049 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);
6050 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
6051 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
6056 mymiplevel = savemiplevel;
6057 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6059 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);
6060 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
6061 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
6066 mymiplevel = savemiplevel;
6067 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6069 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);
6070 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
6071 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
6077 Mem_Free(basepixels);
6082 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
6083 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
6086 unsigned char *temp1, *temp2;
6087 skinframe_t *skinframe;
6089 if (cls.state == ca_dedicated)
6092 // if already loaded just return it, otherwise make a new skinframe
6093 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
6094 if (skinframe && skinframe->base)
6097 skinframe->stain = NULL;
6098 skinframe->merged = NULL;
6099 skinframe->base = NULL;
6100 skinframe->pants = NULL;
6101 skinframe->shirt = NULL;
6102 skinframe->nmap = NULL;
6103 skinframe->gloss = NULL;
6104 skinframe->glow = NULL;
6105 skinframe->fog = NULL;
6106 skinframe->reflect = NULL;
6107 skinframe->hasalpha = false;
6109 // if no data was provided, then clearly the caller wanted to get a blank skinframe
6113 if (developer_loading.integer)
6114 Con_Printf("loading 32bit skin \"%s\"\n", name);
6116 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
6118 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6119 temp2 = temp1 + width * height * 4;
6120 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6121 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);
6124 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
6125 if (textureflags & TEXF_ALPHA)
6127 for (i = 3;i < width * height * 4;i += 4)
6129 if (skindata[i] < 255)
6131 skinframe->hasalpha = true;
6135 if (r_loadfog && skinframe->hasalpha)
6137 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
6138 memcpy(fogpixels, skindata, width * height * 4);
6139 for (i = 0;i < width * height * 4;i += 4)
6140 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
6141 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
6142 Mem_Free(fogpixels);
6146 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
6147 //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]);
6152 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
6156 skinframe_t *skinframe;
6158 if (cls.state == ca_dedicated)
6161 // if already loaded just return it, otherwise make a new skinframe
6162 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6163 if (skinframe && skinframe->base)
6166 skinframe->stain = NULL;
6167 skinframe->merged = NULL;
6168 skinframe->base = NULL;
6169 skinframe->pants = NULL;
6170 skinframe->shirt = NULL;
6171 skinframe->nmap = NULL;
6172 skinframe->gloss = NULL;
6173 skinframe->glow = NULL;
6174 skinframe->fog = NULL;
6175 skinframe->reflect = NULL;
6176 skinframe->hasalpha = false;
6178 // if no data was provided, then clearly the caller wanted to get a blank skinframe
6182 if (developer_loading.integer)
6183 Con_Printf("loading quake skin \"%s\"\n", name);
6185 // 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)
6186 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
6187 memcpy(skinframe->qpixels, skindata, width*height);
6188 skinframe->qwidth = width;
6189 skinframe->qheight = height;
6192 for (i = 0;i < width * height;i++)
6193 featuresmask |= palette_featureflags[skindata[i]];
6195 skinframe->hasalpha = false;
6196 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
6197 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
6198 skinframe->qgeneratemerged = true;
6199 skinframe->qgeneratebase = skinframe->qhascolormapping;
6200 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
6202 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
6203 //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]);
6208 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
6212 unsigned char *skindata;
6214 if (!skinframe->qpixels)
6217 if (!skinframe->qhascolormapping)
6218 colormapped = false;
6222 if (!skinframe->qgeneratebase)
6227 if (!skinframe->qgeneratemerged)
6231 width = skinframe->qwidth;
6232 height = skinframe->qheight;
6233 skindata = skinframe->qpixels;
6235 if (skinframe->qgeneratenmap)
6237 unsigned char *temp1, *temp2;
6238 skinframe->qgeneratenmap = false;
6239 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6240 temp2 = temp1 + width * height * 4;
6241 // use either a custom palette or the quake palette
6242 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
6243 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6244 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);
6248 if (skinframe->qgenerateglow)
6250 skinframe->qgenerateglow = false;
6251 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
6256 skinframe->qgeneratebase = false;
6257 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);
6258 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
6259 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
6263 skinframe->qgeneratemerged = false;
6264 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);
6267 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
6269 Mem_Free(skinframe->qpixels);
6270 skinframe->qpixels = NULL;
6274 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)
6277 skinframe_t *skinframe;
6279 if (cls.state == ca_dedicated)
6282 // if already loaded just return it, otherwise make a new skinframe
6283 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6284 if (skinframe && skinframe->base)
6287 skinframe->stain = NULL;
6288 skinframe->merged = NULL;
6289 skinframe->base = NULL;
6290 skinframe->pants = NULL;
6291 skinframe->shirt = NULL;
6292 skinframe->nmap = NULL;
6293 skinframe->gloss = NULL;
6294 skinframe->glow = NULL;
6295 skinframe->fog = NULL;
6296 skinframe->reflect = NULL;
6297 skinframe->hasalpha = false;
6299 // if no data was provided, then clearly the caller wanted to get a blank skinframe
6303 if (developer_loading.integer)
6304 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
6306 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
6307 if (textureflags & TEXF_ALPHA)
6309 for (i = 0;i < width * height;i++)
6311 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
6313 skinframe->hasalpha = true;
6317 if (r_loadfog && skinframe->hasalpha)
6318 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
6321 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
6322 //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]);
6327 skinframe_t *R_SkinFrame_LoadMissing(void)
6329 skinframe_t *skinframe;
6331 if (cls.state == ca_dedicated)
6334 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
6335 skinframe->stain = NULL;
6336 skinframe->merged = NULL;
6337 skinframe->base = NULL;
6338 skinframe->pants = NULL;
6339 skinframe->shirt = NULL;
6340 skinframe->nmap = NULL;
6341 skinframe->gloss = NULL;
6342 skinframe->glow = NULL;
6343 skinframe->fog = NULL;
6344 skinframe->reflect = NULL;
6345 skinframe->hasalpha = false;
6347 skinframe->avgcolor[0] = rand() / RAND_MAX;
6348 skinframe->avgcolor[1] = rand() / RAND_MAX;
6349 skinframe->avgcolor[2] = rand() / RAND_MAX;
6350 skinframe->avgcolor[3] = 1;
6355 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
6356 typedef struct suffixinfo_s
6359 qboolean flipx, flipy, flipdiagonal;
6362 static suffixinfo_t suffix[3][6] =
6365 {"px", false, false, false},
6366 {"nx", false, false, false},
6367 {"py", false, false, false},
6368 {"ny", false, false, false},
6369 {"pz", false, false, false},
6370 {"nz", false, false, false}
6373 {"posx", false, false, false},
6374 {"negx", false, false, false},
6375 {"posy", false, false, false},
6376 {"negy", false, false, false},
6377 {"posz", false, false, false},
6378 {"negz", false, false, false}
6381 {"rt", true, false, true},
6382 {"lf", false, true, true},
6383 {"ft", true, true, false},
6384 {"bk", false, false, false},
6385 {"up", true, false, true},
6386 {"dn", true, false, true}
6390 static int componentorder[4] = {0, 1, 2, 3};
6392 rtexture_t *R_LoadCubemap(const char *basename)
6394 int i, j, cubemapsize;
6395 unsigned char *cubemappixels, *image_buffer;
6396 rtexture_t *cubemaptexture;
6398 // must start 0 so the first loadimagepixels has no requested width/height
6400 cubemappixels = NULL;
6401 cubemaptexture = NULL;
6402 // keep trying different suffix groups (posx, px, rt) until one loads
6403 for (j = 0;j < 3 && !cubemappixels;j++)
6405 // load the 6 images in the suffix group
6406 for (i = 0;i < 6;i++)
6408 // generate an image name based on the base and and suffix
6409 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
6411 if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
6413 // an image loaded, make sure width and height are equal
6414 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
6416 // if this is the first image to load successfully, allocate the cubemap memory
6417 if (!cubemappixels && image_width >= 1)
6419 cubemapsize = image_width;
6420 // note this clears to black, so unavailable sides are black
6421 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
6423 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
6425 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);
6428 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
6430 Mem_Free(image_buffer);
6434 // if a cubemap loaded, upload it
6437 if (developer_loading.integer)
6438 Con_Printf("loading cubemap \"%s\"\n", basename);
6440 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6441 Mem_Free(cubemappixels);
6445 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
6446 if (developer_loading.integer)
6448 Con_Printf("(tried tried images ");
6449 for (j = 0;j < 3;j++)
6450 for (i = 0;i < 6;i++)
6451 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
6452 Con_Print(" and was unable to find any of them).\n");
6455 return cubemaptexture;
6458 rtexture_t *R_GetCubemap(const char *basename)
6461 for (i = 0;i < r_texture_numcubemaps;i++)
6462 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
6463 return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
6464 if (i >= MAX_CUBEMAPS)
6465 return r_texture_whitecube;
6466 r_texture_numcubemaps++;
6467 strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
6468 r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
6469 return r_texture_cubemaps[i].texture;
6472 void R_FreeCubemaps(void)
6475 for (i = 0;i < r_texture_numcubemaps;i++)
6477 if (developer_loading.integer)
6478 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
6479 if (r_texture_cubemaps[i].texture)
6480 R_FreeTexture(r_texture_cubemaps[i].texture);
6482 r_texture_numcubemaps = 0;
6485 void R_Main_FreeViewCache(void)
6487 if (r_refdef.viewcache.entityvisible)
6488 Mem_Free(r_refdef.viewcache.entityvisible);
6489 if (r_refdef.viewcache.world_pvsbits)
6490 Mem_Free(r_refdef.viewcache.world_pvsbits);
6491 if (r_refdef.viewcache.world_leafvisible)
6492 Mem_Free(r_refdef.viewcache.world_leafvisible);
6493 if (r_refdef.viewcache.world_surfacevisible)
6494 Mem_Free(r_refdef.viewcache.world_surfacevisible);
6495 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
6498 void R_Main_ResizeViewCache(void)
6500 int numentities = r_refdef.scene.numentities;
6501 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
6502 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
6503 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
6504 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
6505 if (r_refdef.viewcache.maxentities < numentities)
6507 r_refdef.viewcache.maxentities = numentities;
6508 if (r_refdef.viewcache.entityvisible)
6509 Mem_Free(r_refdef.viewcache.entityvisible);
6510 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
6512 if (r_refdef.viewcache.world_numclusters != numclusters)
6514 r_refdef.viewcache.world_numclusters = numclusters;
6515 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
6516 if (r_refdef.viewcache.world_pvsbits)
6517 Mem_Free(r_refdef.viewcache.world_pvsbits);
6518 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
6520 if (r_refdef.viewcache.world_numleafs != numleafs)
6522 r_refdef.viewcache.world_numleafs = numleafs;
6523 if (r_refdef.viewcache.world_leafvisible)
6524 Mem_Free(r_refdef.viewcache.world_leafvisible);
6525 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
6527 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
6529 r_refdef.viewcache.world_numsurfaces = numsurfaces;
6530 if (r_refdef.viewcache.world_surfacevisible)
6531 Mem_Free(r_refdef.viewcache.world_surfacevisible);
6532 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
6536 extern rtexture_t *loadingscreentexture;
6537 void gl_main_start(void)
6539 loadingscreentexture = NULL;
6540 r_texture_blanknormalmap = NULL;
6541 r_texture_white = NULL;
6542 r_texture_grey128 = NULL;
6543 r_texture_black = NULL;
6544 r_texture_whitecube = NULL;
6545 r_texture_normalizationcube = NULL;
6546 r_texture_fogattenuation = NULL;
6547 r_texture_fogheighttexture = NULL;
6548 r_texture_gammaramps = NULL;
6549 r_texture_numcubemaps = 0;
6551 r_loaddds = r_texture_dds_load.integer != 0;
6552 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
6554 switch(vid.renderpath)
6556 case RENDERPATH_GL20:
6557 case RENDERPATH_D3D9:
6558 case RENDERPATH_D3D10:
6559 case RENDERPATH_D3D11:
6560 case RENDERPATH_SOFT:
6561 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6562 Cvar_SetValueQuick(&gl_combine, 1);
6563 Cvar_SetValueQuick(&r_glsl, 1);
6564 r_loadnormalmap = true;
6568 case RENDERPATH_GL13:
6569 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6570 Cvar_SetValueQuick(&gl_combine, 1);
6571 Cvar_SetValueQuick(&r_glsl, 0);
6572 r_loadnormalmap = false;
6573 r_loadgloss = false;
6576 case RENDERPATH_GL11:
6577 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6578 Cvar_SetValueQuick(&gl_combine, 0);
6579 Cvar_SetValueQuick(&r_glsl, 0);
6580 r_loadnormalmap = false;
6581 r_loadgloss = false;
6584 case RENDERPATH_GLES2:
6585 Cvar_SetValueQuick(&r_textureunits, 1);
6586 Cvar_SetValueQuick(&gl_combine, 1);
6587 Cvar_SetValueQuick(&r_glsl, 1);
6588 r_loadnormalmap = true;
6589 r_loadgloss = false;
6595 R_FrameData_Reset();
6599 memset(r_queries, 0, sizeof(r_queries));
6601 r_qwskincache = NULL;
6602 r_qwskincache_size = 0;
6604 // set up r_skinframe loading system for textures
6605 memset(&r_skinframe, 0, sizeof(r_skinframe));
6606 r_skinframe.loadsequence = 1;
6607 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
6609 r_main_texturepool = R_AllocTexturePool();
6610 R_BuildBlankTextures();
6612 if (vid.support.arb_texture_cube_map)
6615 R_BuildNormalizationCube();
6617 r_texture_fogattenuation = NULL;
6618 r_texture_fogheighttexture = NULL;
6619 r_texture_gammaramps = NULL;
6620 //r_texture_fogintensity = NULL;
6621 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6622 memset(&r_waterstate, 0, sizeof(r_waterstate));
6623 r_glsl_permutation = NULL;
6624 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
6625 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
6626 glslshaderstring = NULL;
6628 r_hlsl_permutation = NULL;
6629 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
6630 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
6632 hlslshaderstring = NULL;
6633 memset(&r_svbsp, 0, sizeof (r_svbsp));
6635 r_refdef.fogmasktable_density = 0;
6638 void gl_main_shutdown(void)
6641 R_FrameData_Reset();
6643 R_Main_FreeViewCache();
6645 switch(vid.renderpath)
6647 case RENDERPATH_GL11:
6648 case RENDERPATH_GL13:
6649 case RENDERPATH_GL20:
6650 case RENDERPATH_GLES2:
6652 qglDeleteQueriesARB(r_maxqueries, r_queries);
6654 case RENDERPATH_D3D9:
6655 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6657 case RENDERPATH_D3D10:
6658 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6660 case RENDERPATH_D3D11:
6661 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6663 case RENDERPATH_SOFT:
6669 memset(r_queries, 0, sizeof(r_queries));
6671 r_qwskincache = NULL;
6672 r_qwskincache_size = 0;
6674 // clear out the r_skinframe state
6675 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
6676 memset(&r_skinframe, 0, sizeof(r_skinframe));
6679 Mem_Free(r_svbsp.nodes);
6680 memset(&r_svbsp, 0, sizeof (r_svbsp));
6681 R_FreeTexturePool(&r_main_texturepool);
6682 loadingscreentexture = NULL;
6683 r_texture_blanknormalmap = NULL;
6684 r_texture_white = NULL;
6685 r_texture_grey128 = NULL;
6686 r_texture_black = NULL;
6687 r_texture_whitecube = NULL;
6688 r_texture_normalizationcube = NULL;
6689 r_texture_fogattenuation = NULL;
6690 r_texture_fogheighttexture = NULL;
6691 r_texture_gammaramps = NULL;
6692 r_texture_numcubemaps = 0;
6693 //r_texture_fogintensity = NULL;
6694 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6695 memset(&r_waterstate, 0, sizeof(r_waterstate));
6698 r_glsl_permutation = NULL;
6699 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
6700 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
6701 glslshaderstring = NULL;
6703 r_hlsl_permutation = NULL;
6704 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
6705 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
6707 hlslshaderstring = NULL;
6710 extern void CL_ParseEntityLump(char *entitystring);
6711 void gl_main_newmap(void)
6713 // FIXME: move this code to client
6714 char *entities, entname[MAX_QPATH];
6716 Mem_Free(r_qwskincache);
6717 r_qwskincache = NULL;
6718 r_qwskincache_size = 0;
6721 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
6722 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
6724 CL_ParseEntityLump(entities);
6728 if (cl.worldmodel->brush.entities)
6729 CL_ParseEntityLump(cl.worldmodel->brush.entities);
6731 R_Main_FreeViewCache();
6733 R_FrameData_Reset();
6736 void GL_Main_Init(void)
6738 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
6740 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
6741 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
6742 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
6743 if (gamemode == GAME_NEHAHRA)
6745 Cvar_RegisterVariable (&gl_fogenable);
6746 Cvar_RegisterVariable (&gl_fogdensity);
6747 Cvar_RegisterVariable (&gl_fogred);
6748 Cvar_RegisterVariable (&gl_foggreen);
6749 Cvar_RegisterVariable (&gl_fogblue);
6750 Cvar_RegisterVariable (&gl_fogstart);
6751 Cvar_RegisterVariable (&gl_fogend);
6752 Cvar_RegisterVariable (&gl_skyclip);
6754 Cvar_RegisterVariable(&r_motionblur);
6755 Cvar_RegisterVariable(&r_motionblur_maxblur);
6756 Cvar_RegisterVariable(&r_motionblur_bmin);
6757 Cvar_RegisterVariable(&r_motionblur_vmin);
6758 Cvar_RegisterVariable(&r_motionblur_vmax);
6759 Cvar_RegisterVariable(&r_motionblur_vcoeff);
6760 Cvar_RegisterVariable(&r_motionblur_randomize);
6761 Cvar_RegisterVariable(&r_damageblur);
6762 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
6763 Cvar_RegisterVariable(&r_equalize_entities_minambient);
6764 Cvar_RegisterVariable(&r_equalize_entities_by);
6765 Cvar_RegisterVariable(&r_equalize_entities_to);
6766 Cvar_RegisterVariable(&r_depthfirst);
6767 Cvar_RegisterVariable(&r_useinfinitefarclip);
6768 Cvar_RegisterVariable(&r_farclip_base);
6769 Cvar_RegisterVariable(&r_farclip_world);
6770 Cvar_RegisterVariable(&r_nearclip);
6771 Cvar_RegisterVariable(&r_showbboxes);
6772 Cvar_RegisterVariable(&r_showsurfaces);
6773 Cvar_RegisterVariable(&r_showtris);
6774 Cvar_RegisterVariable(&r_shownormals);
6775 Cvar_RegisterVariable(&r_showlighting);
6776 Cvar_RegisterVariable(&r_showshadowvolumes);
6777 Cvar_RegisterVariable(&r_showcollisionbrushes);
6778 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
6779 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
6780 Cvar_RegisterVariable(&r_showdisabledepthtest);
6781 Cvar_RegisterVariable(&r_drawportals);
6782 Cvar_RegisterVariable(&r_drawentities);
6783 Cvar_RegisterVariable(&r_draw2d);
6784 Cvar_RegisterVariable(&r_drawworld);
6785 Cvar_RegisterVariable(&r_cullentities_trace);
6786 Cvar_RegisterVariable(&r_cullentities_trace_samples);
6787 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
6788 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
6789 Cvar_RegisterVariable(&r_cullentities_trace_delay);
6790 Cvar_RegisterVariable(&r_drawviewmodel);
6791 Cvar_RegisterVariable(&r_drawexteriormodel);
6792 Cvar_RegisterVariable(&r_speeds);
6793 Cvar_RegisterVariable(&r_fullbrights);
6794 Cvar_RegisterVariable(&r_wateralpha);
6795 Cvar_RegisterVariable(&r_dynamic);
6796 Cvar_RegisterVariable(&r_fakelight);
6797 Cvar_RegisterVariable(&r_fakelight_intensity);
6798 Cvar_RegisterVariable(&r_fullbright);
6799 Cvar_RegisterVariable(&r_shadows);
6800 Cvar_RegisterVariable(&r_shadows_darken);
6801 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
6802 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
6803 Cvar_RegisterVariable(&r_shadows_throwdistance);
6804 Cvar_RegisterVariable(&r_shadows_throwdirection);
6805 Cvar_RegisterVariable(&r_shadows_focus);
6806 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
6807 Cvar_RegisterVariable(&r_q1bsp_skymasking);
6808 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
6809 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
6810 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
6811 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
6812 Cvar_RegisterVariable(&r_fog_exp2);
6813 Cvar_RegisterVariable(&r_drawfog);
6814 Cvar_RegisterVariable(&r_transparentdepthmasking);
6815 Cvar_RegisterVariable(&r_texture_dds_load);
6816 Cvar_RegisterVariable(&r_texture_dds_save);
6817 Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
6818 Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
6819 Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
6820 Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
6821 Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
6822 Cvar_RegisterVariable(&r_textureunits);
6823 Cvar_RegisterVariable(&gl_combine);
6824 Cvar_RegisterVariable(&r_glsl);
6825 Cvar_RegisterVariable(&r_glsl_deluxemapping);
6826 Cvar_RegisterVariable(&r_glsl_offsetmapping);
6827 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
6828 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
6829 Cvar_RegisterVariable(&r_glsl_postprocess);
6830 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
6831 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
6832 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
6833 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
6834 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
6835 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
6836 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
6837 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
6839 Cvar_RegisterVariable(&r_water);
6840 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
6841 Cvar_RegisterVariable(&r_water_clippingplanebias);
6842 Cvar_RegisterVariable(&r_water_refractdistort);
6843 Cvar_RegisterVariable(&r_water_reflectdistort);
6844 Cvar_RegisterVariable(&r_water_scissormode);
6845 Cvar_RegisterVariable(&r_lerpsprites);
6846 Cvar_RegisterVariable(&r_lerpmodels);
6847 Cvar_RegisterVariable(&r_lerplightstyles);
6848 Cvar_RegisterVariable(&r_waterscroll);
6849 Cvar_RegisterVariable(&r_bloom);
6850 Cvar_RegisterVariable(&r_bloom_colorscale);
6851 Cvar_RegisterVariable(&r_bloom_brighten);
6852 Cvar_RegisterVariable(&r_bloom_blur);
6853 Cvar_RegisterVariable(&r_bloom_resolution);
6854 Cvar_RegisterVariable(&r_bloom_colorexponent);
6855 Cvar_RegisterVariable(&r_bloom_colorsubtract);
6856 Cvar_RegisterVariable(&r_hdr);
6857 Cvar_RegisterVariable(&r_hdr_scenebrightness);
6858 Cvar_RegisterVariable(&r_hdr_glowintensity);
6859 Cvar_RegisterVariable(&r_hdr_range);
6860 Cvar_RegisterVariable(&r_hdr_irisadaptation);
6861 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
6862 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
6863 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
6864 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
6865 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
6866 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
6867 Cvar_RegisterVariable(&developer_texturelogging);
6868 Cvar_RegisterVariable(&gl_lightmaps);
6869 Cvar_RegisterVariable(&r_test);
6870 Cvar_RegisterVariable(&r_glsl_saturation);
6871 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
6872 Cvar_RegisterVariable(&r_framedatasize);
6873 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
6874 Cvar_SetValue("r_fullbrights", 0);
6875 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
6877 Cvar_RegisterVariable(&r_track_sprites);
6878 Cvar_RegisterVariable(&r_track_sprites_flags);
6879 Cvar_RegisterVariable(&r_track_sprites_scalew);
6880 Cvar_RegisterVariable(&r_track_sprites_scaleh);
6881 Cvar_RegisterVariable(&r_overheadsprites_perspective);
6882 Cvar_RegisterVariable(&r_overheadsprites_pushback);
6883 Cvar_RegisterVariable(&r_overheadsprites_scalex);
6884 Cvar_RegisterVariable(&r_overheadsprites_scaley);
6887 extern void R_Textures_Init(void);
6888 extern void GL_Draw_Init(void);
6889 extern void GL_Main_Init(void);
6890 extern void R_Shadow_Init(void);
6891 extern void R_Sky_Init(void);
6892 extern void GL_Surf_Init(void);
6893 extern void R_Particles_Init(void);
6894 extern void R_Explosion_Init(void);
6895 extern void gl_backend_init(void);
6896 extern void Sbar_Init(void);
6897 extern void R_LightningBeams_Init(void);
6898 extern void Mod_RenderInit(void);
6899 extern void Font_Init(void);
6901 void Render_Init(void)
6914 R_LightningBeams_Init();
6923 extern char *ENGINE_EXTENSIONS;
6926 gl_renderer = (const char *)qglGetString(GL_RENDERER);
6927 gl_vendor = (const char *)qglGetString(GL_VENDOR);
6928 gl_version = (const char *)qglGetString(GL_VERSION);
6929 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
6933 if (!gl_platformextensions)
6934 gl_platformextensions = "";
6936 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
6937 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
6938 Con_Printf("GL_VERSION: %s\n", gl_version);
6939 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
6940 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
6942 VID_CheckExtensions();
6944 // LordHavoc: report supported extensions
6945 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
6947 // clear to black (loading plaque will be seen over this)
6948 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6951 int R_CullBox(const vec3_t mins, const vec3_t maxs)
6955 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
6957 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
6960 p = r_refdef.view.frustum + i;
6965 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6969 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6973 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6977 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6981 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6985 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6989 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6993 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7001 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
7005 for (i = 0;i < numplanes;i++)
7012 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7016 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7020 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7024 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7028 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7032 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7036 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7040 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7048 //==================================================================================
7050 // LordHavoc: this stores temporary data used within the same frame
7052 typedef struct r_framedata_mem_s
7054 struct r_framedata_mem_s *purge; // older mem block to free on next frame
7055 size_t size; // how much usable space
7056 size_t current; // how much space in use
7057 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
7058 size_t wantedsize; // how much space was allocated
7059 unsigned char *data; // start of real data (16byte aligned)
7063 static r_framedata_mem_t *r_framedata_mem;
7065 void R_FrameData_Reset(void)
7067 while (r_framedata_mem)
7069 r_framedata_mem_t *next = r_framedata_mem->purge;
7070 Mem_Free(r_framedata_mem);
7071 r_framedata_mem = next;
7075 void R_FrameData_Resize(void)
7078 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
7079 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
7080 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
7082 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
7083 newmem->wantedsize = wantedsize;
7084 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
7085 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
7086 newmem->current = 0;
7088 newmem->purge = r_framedata_mem;
7089 r_framedata_mem = newmem;
7093 void R_FrameData_NewFrame(void)
7095 R_FrameData_Resize();
7096 if (!r_framedata_mem)
7098 // if we ran out of space on the last frame, free the old memory now
7099 while (r_framedata_mem->purge)
7101 // repeatedly remove the second item in the list, leaving only head
7102 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
7103 Mem_Free(r_framedata_mem->purge);
7104 r_framedata_mem->purge = next;
7106 // reset the current mem pointer
7107 r_framedata_mem->current = 0;
7108 r_framedata_mem->mark = 0;
7111 void *R_FrameData_Alloc(size_t size)
7115 // align to 16 byte boundary - the data pointer is already aligned, so we
7116 // only need to ensure the size of every allocation is also aligned
7117 size = (size + 15) & ~15;
7119 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
7121 // emergency - we ran out of space, allocate more memory
7122 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
7123 R_FrameData_Resize();
7126 data = r_framedata_mem->data + r_framedata_mem->current;
7127 r_framedata_mem->current += size;
7129 // count the usage for stats
7130 r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
7131 r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
7133 return (void *)data;
7136 void *R_FrameData_Store(size_t size, void *data)
7138 void *d = R_FrameData_Alloc(size);
7140 memcpy(d, data, size);
7144 void R_FrameData_SetMark(void)
7146 if (!r_framedata_mem)
7148 r_framedata_mem->mark = r_framedata_mem->current;
7151 void R_FrameData_ReturnToMark(void)
7153 if (!r_framedata_mem)
7155 r_framedata_mem->current = r_framedata_mem->mark;
7158 //==================================================================================
7160 // LordHavoc: animcache originally written by Echon, rewritten since then
7163 * Animation cache prevents re-generating mesh data for an animated model
7164 * multiple times in one frame for lighting, shadowing, reflections, etc.
7167 void R_AnimCache_Free(void)
7171 void R_AnimCache_ClearCache(void)
7174 entity_render_t *ent;
7176 for (i = 0;i < r_refdef.scene.numentities;i++)
7178 ent = r_refdef.scene.entities[i];
7179 ent->animcache_vertex3f = NULL;
7180 ent->animcache_normal3f = NULL;
7181 ent->animcache_svector3f = NULL;
7182 ent->animcache_tvector3f = NULL;
7183 ent->animcache_vertexmesh = NULL;
7184 ent->animcache_vertex3fbuffer = NULL;
7185 ent->animcache_vertexmeshbuffer = NULL;
7189 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
7193 // check if we need the meshbuffers
7194 if (!vid.useinterleavedarrays)
7197 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
7198 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
7199 // TODO: upload vertex3f buffer?
7200 if (ent->animcache_vertexmesh)
7202 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
7203 for (i = 0;i < numvertices;i++)
7204 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7205 if (ent->animcache_svector3f)
7206 for (i = 0;i < numvertices;i++)
7207 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
7208 if (ent->animcache_tvector3f)
7209 for (i = 0;i < numvertices;i++)
7210 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
7211 if (ent->animcache_normal3f)
7212 for (i = 0;i < numvertices;i++)
7213 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
7214 // TODO: upload vertexmeshbuffer?
7218 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
7220 dp_model_t *model = ent->model;
7222 // see if it's already cached this frame
7223 if (ent->animcache_vertex3f)
7225 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
7226 if (wantnormals || wanttangents)
7228 if (ent->animcache_normal3f)
7229 wantnormals = false;
7230 if (ent->animcache_svector3f)
7231 wanttangents = false;
7232 if (wantnormals || wanttangents)
7234 numvertices = model->surfmesh.num_vertices;
7236 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7239 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7240 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7242 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
7243 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7249 // see if this ent is worth caching
7250 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
7252 // get some memory for this entity and generate mesh data
7253 numvertices = model->surfmesh.num_vertices;
7254 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7256 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7259 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7260 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7262 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
7263 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7268 void R_AnimCache_CacheVisibleEntities(void)
7271 qboolean wantnormals = true;
7272 qboolean wanttangents = !r_showsurfaces.integer;
7274 switch(vid.renderpath)
7276 case RENDERPATH_GL20:
7277 case RENDERPATH_D3D9:
7278 case RENDERPATH_D3D10:
7279 case RENDERPATH_D3D11:
7280 case RENDERPATH_GLES2:
7282 case RENDERPATH_GL13:
7283 case RENDERPATH_GL11:
7284 wanttangents = false;
7286 case RENDERPATH_SOFT:
7290 if (r_shownormals.integer)
7291 wanttangents = wantnormals = true;
7293 // TODO: thread this
7294 // NOTE: R_PrepareRTLights() also caches entities
7296 for (i = 0;i < r_refdef.scene.numentities;i++)
7297 if (r_refdef.viewcache.entityvisible[i])
7298 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
7301 //==================================================================================
7303 static void R_View_UpdateEntityLighting (void)
7306 entity_render_t *ent;
7307 vec3_t tempdiffusenormal, avg;
7308 vec_t f, fa, fd, fdd;
7309 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
7311 for (i = 0;i < r_refdef.scene.numentities;i++)
7313 ent = r_refdef.scene.entities[i];
7315 // skip unseen models
7316 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
7320 if (ent->model && ent->model->brush.num_leafs)
7322 // TODO: use modellight for r_ambient settings on world?
7323 VectorSet(ent->modellight_ambient, 0, 0, 0);
7324 VectorSet(ent->modellight_diffuse, 0, 0, 0);
7325 VectorSet(ent->modellight_lightdir, 0, 0, 1);
7329 // fetch the lighting from the worldmodel data
7330 VectorClear(ent->modellight_ambient);
7331 VectorClear(ent->modellight_diffuse);
7332 VectorClear(tempdiffusenormal);
7333 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
7336 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7338 // complete lightning for lit sprites
7339 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
7340 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
7342 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
7343 org[2] = org[2] + r_overheadsprites_pushback.value;
7344 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
7347 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
7349 if(ent->flags & RENDER_EQUALIZE)
7351 // first fix up ambient lighting...
7352 if(r_equalize_entities_minambient.value > 0)
7354 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7357 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
7358 if(fa < r_equalize_entities_minambient.value * fd)
7361 // fa'/fd' = minambient
7362 // fa'+0.25*fd' = fa+0.25*fd
7364 // fa' = fd' * minambient
7365 // fd'*(0.25+minambient) = fa+0.25*fd
7367 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
7368 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
7370 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
7371 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
7372 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
7373 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7378 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
7380 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
7381 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7385 // adjust brightness and saturation to target
7386 avg[0] = avg[1] = avg[2] = fa / f;
7387 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
7388 avg[0] = avg[1] = avg[2] = fd / f;
7389 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
7395 VectorSet(ent->modellight_ambient, 1, 1, 1);
7397 // move the light direction into modelspace coordinates for lighting code
7398 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
7399 if(VectorLength2(ent->modellight_lightdir) == 0)
7400 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
7401 VectorNormalize(ent->modellight_lightdir);
7405 #define MAX_LINEOFSIGHTTRACES 64
7407 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
7410 vec3_t boxmins, boxmaxs;
7413 dp_model_t *model = r_refdef.scene.worldmodel;
7415 if (!model || !model->brush.TraceLineOfSight)
7418 // expand the box a little
7419 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
7420 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
7421 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
7422 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
7423 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
7424 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
7426 // return true if eye is inside enlarged box
7427 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
7431 VectorCopy(eye, start);
7432 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
7433 if (model->brush.TraceLineOfSight(model, start, end))
7436 // try various random positions
7437 for (i = 0;i < numsamples;i++)
7439 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
7440 if (model->brush.TraceLineOfSight(model, start, end))
7448 static void R_View_UpdateEntityVisible (void)
7453 entity_render_t *ent;
7455 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7456 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7457 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
7458 : RENDER_EXTERIORMODEL;
7459 if (!r_drawviewmodel.integer)
7460 renderimask |= RENDER_VIEWMODEL;
7461 if (!r_drawexteriormodel.integer)
7462 renderimask |= RENDER_EXTERIORMODEL;
7463 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
7465 // worldmodel can check visibility
7466 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
7467 for (i = 0;i < r_refdef.scene.numentities;i++)
7469 ent = r_refdef.scene.entities[i];
7470 if (!(ent->flags & renderimask))
7471 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)))
7472 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))
7473 r_refdef.viewcache.entityvisible[i] = true;
7475 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
7476 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
7478 for (i = 0;i < r_refdef.scene.numentities;i++)
7480 ent = r_refdef.scene.entities[i];
7481 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
7483 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
7485 continue; // temp entities do pvs only
7486 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
7487 ent->last_trace_visibility = realtime;
7488 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
7489 r_refdef.viewcache.entityvisible[i] = 0;
7496 // no worldmodel or it can't check visibility
7497 for (i = 0;i < r_refdef.scene.numentities;i++)
7499 ent = r_refdef.scene.entities[i];
7500 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));
7505 /// only used if skyrendermasked, and normally returns false
7506 int R_DrawBrushModelsSky (void)
7509 entity_render_t *ent;
7512 for (i = 0;i < r_refdef.scene.numentities;i++)
7514 if (!r_refdef.viewcache.entityvisible[i])
7516 ent = r_refdef.scene.entities[i];
7517 if (!ent->model || !ent->model->DrawSky)
7519 ent->model->DrawSky(ent);
7525 static void R_DrawNoModel(entity_render_t *ent);
7526 static void R_DrawModels(void)
7529 entity_render_t *ent;
7531 for (i = 0;i < r_refdef.scene.numentities;i++)
7533 if (!r_refdef.viewcache.entityvisible[i])
7535 ent = r_refdef.scene.entities[i];
7536 r_refdef.stats.entities++;
7537 if (ent->model && ent->model->Draw != NULL)
7538 ent->model->Draw(ent);
7544 static void R_DrawModelsDepth(void)
7547 entity_render_t *ent;
7549 for (i = 0;i < r_refdef.scene.numentities;i++)
7551 if (!r_refdef.viewcache.entityvisible[i])
7553 ent = r_refdef.scene.entities[i];
7554 if (ent->model && ent->model->DrawDepth != NULL)
7555 ent->model->DrawDepth(ent);
7559 static void R_DrawModelsDebug(void)
7562 entity_render_t *ent;
7564 for (i = 0;i < r_refdef.scene.numentities;i++)
7566 if (!r_refdef.viewcache.entityvisible[i])
7568 ent = r_refdef.scene.entities[i];
7569 if (ent->model && ent->model->DrawDebug != NULL)
7570 ent->model->DrawDebug(ent);
7574 static void R_DrawModelsAddWaterPlanes(void)
7577 entity_render_t *ent;
7579 for (i = 0;i < r_refdef.scene.numentities;i++)
7581 if (!r_refdef.viewcache.entityvisible[i])
7583 ent = r_refdef.scene.entities[i];
7584 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
7585 ent->model->DrawAddWaterPlanes(ent);
7589 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
7591 if (r_hdr_irisadaptation.integer)
7595 vec3_t diffusenormal;
7600 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
7601 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
7602 brightness = max(0.0000001f, brightness);
7603 goal = r_hdr_irisadaptation_multiplier.value / brightness;
7604 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
7605 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
7606 current = r_hdr_irisadaptation_value.value;
7608 current = min(current + adjust, goal);
7609 else if (current > goal)
7610 current = max(current - adjust, goal);
7611 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
7612 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
7614 else if (r_hdr_irisadaptation_value.value != 1.0f)
7615 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
7618 static void R_View_SetFrustum(const int *scissor)
7621 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
7622 vec3_t forward, left, up, origin, v;
7626 // flipped x coordinates (because x points left here)
7627 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
7628 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
7630 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
7631 switch(vid.renderpath)
7633 case RENDERPATH_D3D9:
7634 case RENDERPATH_D3D10:
7635 case RENDERPATH_D3D11:
7636 case RENDERPATH_SOFT:
7637 // non-flipped y coordinates
7638 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
7639 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
7641 case RENDERPATH_GL11:
7642 case RENDERPATH_GL13:
7643 case RENDERPATH_GL20:
7644 case RENDERPATH_GLES2:
7645 // non-flipped y coordinates
7646 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
7647 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
7652 // we can't trust r_refdef.view.forward and friends in reflected scenes
7653 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
7656 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
7657 r_refdef.view.frustum[0].normal[1] = 0 - 0;
7658 r_refdef.view.frustum[0].normal[2] = -1 - 0;
7659 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
7660 r_refdef.view.frustum[1].normal[1] = 0 + 0;
7661 r_refdef.view.frustum[1].normal[2] = -1 + 0;
7662 r_refdef.view.frustum[2].normal[0] = 0 - 0;
7663 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
7664 r_refdef.view.frustum[2].normal[2] = -1 - 0;
7665 r_refdef.view.frustum[3].normal[0] = 0 + 0;
7666 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
7667 r_refdef.view.frustum[3].normal[2] = -1 + 0;
7671 zNear = r_refdef.nearclip;
7672 nudge = 1.0 - 1.0 / (1<<23);
7673 r_refdef.view.frustum[4].normal[0] = 0 - 0;
7674 r_refdef.view.frustum[4].normal[1] = 0 - 0;
7675 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
7676 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
7677 r_refdef.view.frustum[5].normal[0] = 0 + 0;
7678 r_refdef.view.frustum[5].normal[1] = 0 + 0;
7679 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
7680 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
7686 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
7687 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
7688 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
7689 r_refdef.view.frustum[0].dist = m[15] - m[12];
7691 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
7692 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
7693 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
7694 r_refdef.view.frustum[1].dist = m[15] + m[12];
7696 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
7697 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
7698 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
7699 r_refdef.view.frustum[2].dist = m[15] - m[13];
7701 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
7702 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
7703 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
7704 r_refdef.view.frustum[3].dist = m[15] + m[13];
7706 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
7707 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
7708 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
7709 r_refdef.view.frustum[4].dist = m[15] - m[14];
7711 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
7712 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
7713 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
7714 r_refdef.view.frustum[5].dist = m[15] + m[14];
7717 if (r_refdef.view.useperspective)
7719 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
7720 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]);
7721 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]);
7722 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]);
7723 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]);
7725 // then the normals from the corners relative to origin
7726 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
7727 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
7728 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
7729 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
7731 // in a NORMAL view, forward cross left == up
7732 // in a REFLECTED view, forward cross left == down
7733 // so our cross products above need to be adjusted for a left handed coordinate system
7734 CrossProduct(forward, left, v);
7735 if(DotProduct(v, up) < 0)
7737 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
7738 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
7739 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
7740 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
7743 // Leaving those out was a mistake, those were in the old code, and they
7744 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
7745 // I couldn't reproduce it after adding those normalizations. --blub
7746 VectorNormalize(r_refdef.view.frustum[0].normal);
7747 VectorNormalize(r_refdef.view.frustum[1].normal);
7748 VectorNormalize(r_refdef.view.frustum[2].normal);
7749 VectorNormalize(r_refdef.view.frustum[3].normal);
7751 // make the corners absolute
7752 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
7753 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
7754 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
7755 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
7758 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7760 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
7761 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
7762 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
7763 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
7764 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7768 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
7769 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
7770 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
7771 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
7772 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7773 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
7774 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
7775 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
7776 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
7777 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7779 r_refdef.view.numfrustumplanes = 5;
7781 if (r_refdef.view.useclipplane)
7783 r_refdef.view.numfrustumplanes = 6;
7784 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
7787 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7788 PlaneClassify(r_refdef.view.frustum + i);
7790 // LordHavoc: note to all quake engine coders, Quake had a special case
7791 // for 90 degrees which assumed a square view (wrong), so I removed it,
7792 // Quake2 has it disabled as well.
7794 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
7795 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
7796 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
7797 //PlaneClassify(&frustum[0]);
7799 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
7800 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
7801 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
7802 //PlaneClassify(&frustum[1]);
7804 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
7805 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
7806 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
7807 //PlaneClassify(&frustum[2]);
7809 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
7810 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
7811 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
7812 //PlaneClassify(&frustum[3]);
7815 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
7816 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
7817 //PlaneClassify(&frustum[4]);
7820 void R_View_UpdateWithScissor(const int *myscissor)
7822 R_Main_ResizeViewCache();
7823 R_View_SetFrustum(myscissor);
7824 R_View_WorldVisibility(r_refdef.view.useclipplane);
7825 R_View_UpdateEntityVisible();
7826 R_View_UpdateEntityLighting();
7829 void R_View_Update(void)
7831 R_Main_ResizeViewCache();
7832 R_View_SetFrustum(NULL);
7833 R_View_WorldVisibility(r_refdef.view.useclipplane);
7834 R_View_UpdateEntityVisible();
7835 R_View_UpdateEntityLighting();
7838 void R_SetupView(qboolean allowwaterclippingplane)
7840 const float *customclipplane = NULL;
7842 if (r_refdef.view.useclipplane && allowwaterclippingplane)
7844 // LordHavoc: couldn't figure out how to make this approach the
7845 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
7846 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
7847 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
7848 dist = r_refdef.view.clipplane.dist;
7849 plane[0] = r_refdef.view.clipplane.normal[0];
7850 plane[1] = r_refdef.view.clipplane.normal[1];
7851 plane[2] = r_refdef.view.clipplane.normal[2];
7853 customclipplane = plane;
7856 if (!r_refdef.view.useperspective)
7857 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);
7858 else if (vid.stencil && r_useinfinitefarclip.integer)
7859 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);
7861 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);
7862 R_SetViewport(&r_refdef.view.viewport);
7865 void R_EntityMatrix(const matrix4x4_t *matrix)
7867 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
7869 gl_modelmatrixchanged = false;
7870 gl_modelmatrix = *matrix;
7871 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
7872 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
7873 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
7874 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
7876 switch(vid.renderpath)
7878 case RENDERPATH_D3D9:
7880 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
7881 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
7884 case RENDERPATH_D3D10:
7885 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
7887 case RENDERPATH_D3D11:
7888 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
7890 case RENDERPATH_GL13:
7891 case RENDERPATH_GL11:
7892 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7894 case RENDERPATH_SOFT:
7895 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
7896 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
7898 case RENDERPATH_GL20:
7899 case RENDERPATH_GLES2:
7900 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
7901 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
7907 void R_ResetViewRendering2D(void)
7909 r_viewport_t viewport;
7912 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
7913 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);
7914 R_SetViewport(&viewport);
7915 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
7916 GL_Color(1, 1, 1, 1);
7917 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7918 GL_BlendFunc(GL_ONE, GL_ZERO);
7919 GL_ScissorTest(false);
7920 GL_DepthMask(false);
7921 GL_DepthRange(0, 1);
7922 GL_DepthTest(false);
7923 GL_DepthFunc(GL_LEQUAL);
7924 R_EntityMatrix(&identitymatrix);
7925 R_Mesh_ResetTextureState();
7926 GL_PolygonOffset(0, 0);
7927 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
7928 switch(vid.renderpath)
7930 case RENDERPATH_GL11:
7931 case RENDERPATH_GL13:
7932 case RENDERPATH_GL20:
7933 case RENDERPATH_GLES2:
7934 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
7936 case RENDERPATH_D3D9:
7937 case RENDERPATH_D3D10:
7938 case RENDERPATH_D3D11:
7939 case RENDERPATH_SOFT:
7942 GL_CullFace(GL_NONE);
7945 void R_ResetViewRendering3D(void)
7950 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
7951 GL_Color(1, 1, 1, 1);
7952 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7953 GL_BlendFunc(GL_ONE, GL_ZERO);
7954 GL_ScissorTest(true);
7956 GL_DepthRange(0, 1);
7958 GL_DepthFunc(GL_LEQUAL);
7959 R_EntityMatrix(&identitymatrix);
7960 R_Mesh_ResetTextureState();
7961 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7962 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
7963 switch(vid.renderpath)
7965 case RENDERPATH_GL11:
7966 case RENDERPATH_GL13:
7967 case RENDERPATH_GL20:
7968 case RENDERPATH_GLES2:
7969 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
7971 case RENDERPATH_D3D9:
7972 case RENDERPATH_D3D10:
7973 case RENDERPATH_D3D11:
7974 case RENDERPATH_SOFT:
7977 GL_CullFace(r_refdef.view.cullface_back);
7982 R_RenderView_UpdateViewVectors
7985 static void R_RenderView_UpdateViewVectors(void)
7987 // break apart the view matrix into vectors for various purposes
7988 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
7989 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
7990 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
7991 VectorNegate(r_refdef.view.left, r_refdef.view.right);
7992 // make an inverted copy of the view matrix for tracking sprites
7993 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
7996 void R_RenderScene(void);
7997 void R_RenderWaterPlanes(void);
7999 static void R_Water_StartFrame(void)
8002 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
8003 r_waterstate_waterplane_t *p;
8005 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
8008 switch(vid.renderpath)
8010 case RENDERPATH_GL20:
8011 case RENDERPATH_D3D9:
8012 case RENDERPATH_D3D10:
8013 case RENDERPATH_D3D11:
8014 case RENDERPATH_SOFT:
8015 case RENDERPATH_GLES2:
8017 case RENDERPATH_GL13:
8018 case RENDERPATH_GL11:
8022 // set waterwidth and waterheight to the water resolution that will be
8023 // used (often less than the screen resolution for faster rendering)
8024 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
8025 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
8027 // calculate desired texture sizes
8028 // can't use water if the card does not support the texture size
8029 if (!r_water.integer || r_showsurfaces.integer)
8030 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
8031 else if (vid.support.arb_texture_non_power_of_two)
8033 texturewidth = waterwidth;
8034 textureheight = waterheight;
8035 camerawidth = waterwidth;
8036 cameraheight = waterheight;
8040 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
8041 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
8042 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
8043 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
8046 // allocate textures as needed
8047 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
8049 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8050 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
8052 if (p->texture_refraction)
8053 R_FreeTexture(p->texture_refraction);
8054 p->texture_refraction = NULL;
8055 if (p->texture_reflection)
8056 R_FreeTexture(p->texture_reflection);
8057 p->texture_reflection = NULL;
8058 if (p->texture_camera)
8059 R_FreeTexture(p->texture_camera);
8060 p->texture_camera = NULL;
8062 memset(&r_waterstate, 0, sizeof(r_waterstate));
8063 r_waterstate.texturewidth = texturewidth;
8064 r_waterstate.textureheight = textureheight;
8065 r_waterstate.camerawidth = camerawidth;
8066 r_waterstate.cameraheight = cameraheight;
8069 if (r_waterstate.texturewidth)
8071 r_waterstate.enabled = true;
8073 // when doing a reduced render (HDR) we want to use a smaller area
8074 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
8075 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
8077 // set up variables that will be used in shader setup
8078 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8079 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8080 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8081 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8084 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8085 r_waterstate.numwaterplanes = 0;
8088 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
8090 int triangleindex, planeindex;
8096 r_waterstate_waterplane_t *p;
8097 texture_t *t = R_GetCurrentTexture(surface->texture);
8099 // just use the first triangle with a valid normal for any decisions
8100 VectorClear(normal);
8101 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
8103 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
8104 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
8105 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
8106 TriangleNormal(vert[0], vert[1], vert[2], normal);
8107 if (VectorLength2(normal) >= 0.001)
8111 VectorCopy(normal, plane.normal);
8112 VectorNormalize(plane.normal);
8113 plane.dist = DotProduct(vert[0], plane.normal);
8114 PlaneClassify(&plane);
8115 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
8117 // skip backfaces (except if nocullface is set)
8118 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
8120 VectorNegate(plane.normal, plane.normal);
8122 PlaneClassify(&plane);
8126 // find a matching plane if there is one
8127 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8128 if(p->camera_entity == t->camera_entity)
8129 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
8131 if (planeindex >= r_waterstate.maxwaterplanes)
8132 return; // nothing we can do, out of planes
8134 // if this triangle does not fit any known plane rendered this frame, add one
8135 if (planeindex >= r_waterstate.numwaterplanes)
8137 // store the new plane
8138 r_waterstate.numwaterplanes++;
8140 // clear materialflags and pvs
8141 p->materialflags = 0;
8142 p->pvsvalid = false;
8143 p->camera_entity = t->camera_entity;
8144 VectorCopy(surface->mins, p->mins);
8145 VectorCopy(surface->maxs, p->maxs);
8150 p->mins[0] = min(p->mins[0], surface->mins[0]);
8151 p->mins[1] = min(p->mins[1], surface->mins[1]);
8152 p->mins[2] = min(p->mins[2], surface->mins[2]);
8153 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
8154 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
8155 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
8157 // merge this surface's materialflags into the waterplane
8158 p->materialflags |= t->currentmaterialflags;
8159 if(!(p->materialflags & MATERIALFLAG_CAMERA))
8161 // merge this surface's PVS into the waterplane
8162 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
8163 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
8164 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
8166 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
8172 static void R_Water_ProcessPlanes(void)
8175 r_refdef_view_t originalview;
8176 r_refdef_view_t myview;
8178 r_waterstate_waterplane_t *p;
8181 originalview = r_refdef.view;
8183 // make sure enough textures are allocated
8184 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8186 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8188 if (!p->texture_refraction)
8189 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);
8190 if (!p->texture_refraction)
8193 else if (p->materialflags & MATERIALFLAG_CAMERA)
8195 if (!p->texture_camera)
8196 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);
8197 if (!p->texture_camera)
8201 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8203 if (!p->texture_reflection)
8204 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);
8205 if (!p->texture_reflection)
8211 r_refdef.view = originalview;
8212 r_refdef.view.showdebug = false;
8213 r_refdef.view.width = r_waterstate.waterwidth;
8214 r_refdef.view.height = r_waterstate.waterheight;
8215 r_refdef.view.useclipplane = true;
8216 myview = r_refdef.view;
8217 r_waterstate.renderingscene = true;
8218 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8220 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8222 r_refdef.view = myview;
8223 if(r_water_scissormode.integer)
8226 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8227 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8230 // render reflected scene and copy into texture
8231 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
8232 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
8233 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
8234 r_refdef.view.clipplane = p->plane;
8236 // reverse the cullface settings for this render
8237 r_refdef.view.cullface_front = GL_FRONT;
8238 r_refdef.view.cullface_back = GL_BACK;
8239 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
8241 r_refdef.view.usecustompvs = true;
8243 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8245 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8248 R_ResetViewRendering3D();
8249 R_ClearScreen(r_refdef.fogenabled);
8250 if(r_water_scissormode.integer & 2)
8251 R_View_UpdateWithScissor(myscissor);
8254 if(r_water_scissormode.integer & 1)
8255 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8258 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);
8261 // render the normal view scene and copy into texture
8262 // (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)
8263 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8265 r_refdef.view = myview;
8266 if(r_water_scissormode.integer)
8269 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8270 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8273 r_waterstate.renderingrefraction = true;
8275 r_refdef.view.clipplane = p->plane;
8276 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8277 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8279 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
8281 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8282 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
8283 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8284 R_RenderView_UpdateViewVectors();
8285 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8287 r_refdef.view.usecustompvs = true;
8288 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);
8292 PlaneClassify(&r_refdef.view.clipplane);
8294 R_ResetViewRendering3D();
8295 R_ClearScreen(r_refdef.fogenabled);
8296 if(r_water_scissormode.integer & 2)
8297 R_View_UpdateWithScissor(myscissor);
8300 if(r_water_scissormode.integer & 1)
8301 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8304 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);
8305 r_waterstate.renderingrefraction = false;
8307 else if (p->materialflags & MATERIALFLAG_CAMERA)
8309 r_refdef.view = myview;
8311 r_refdef.view.clipplane = p->plane;
8312 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8313 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8315 r_refdef.view.width = r_waterstate.camerawidth;
8316 r_refdef.view.height = r_waterstate.cameraheight;
8317 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
8318 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
8320 if(p->camera_entity)
8322 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8323 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8326 // note: all of the view is used for displaying... so
8327 // there is no use in scissoring
8329 // reverse the cullface settings for this render
8330 r_refdef.view.cullface_front = GL_FRONT;
8331 r_refdef.view.cullface_back = GL_BACK;
8332 // also reverse the view matrix
8333 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
8334 R_RenderView_UpdateViewVectors();
8335 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8337 r_refdef.view.usecustompvs = true;
8338 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);
8341 // camera needs no clipplane
8342 r_refdef.view.useclipplane = false;
8344 PlaneClassify(&r_refdef.view.clipplane);
8346 R_ResetViewRendering3D();
8347 R_ClearScreen(r_refdef.fogenabled);
8351 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);
8352 r_waterstate.renderingrefraction = false;
8356 r_waterstate.renderingscene = false;
8357 r_refdef.view = originalview;
8358 R_ResetViewRendering3D();
8359 R_ClearScreen(r_refdef.fogenabled);
8363 r_refdef.view = originalview;
8364 r_waterstate.renderingscene = false;
8365 Cvar_SetValueQuick(&r_water, 0);
8366 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
8370 void R_Bloom_StartFrame(void)
8372 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
8374 switch(vid.renderpath)
8376 case RENDERPATH_GL20:
8377 case RENDERPATH_D3D9:
8378 case RENDERPATH_D3D10:
8379 case RENDERPATH_D3D11:
8380 case RENDERPATH_SOFT:
8381 case RENDERPATH_GLES2:
8383 case RENDERPATH_GL13:
8384 case RENDERPATH_GL11:
8388 // set bloomwidth and bloomheight to the bloom resolution that will be
8389 // used (often less than the screen resolution for faster rendering)
8390 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
8391 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
8392 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
8393 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
8394 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
8396 // calculate desired texture sizes
8397 if (vid.support.arb_texture_non_power_of_two)
8399 screentexturewidth = r_refdef.view.width;
8400 screentextureheight = r_refdef.view.height;
8401 bloomtexturewidth = r_bloomstate.bloomwidth;
8402 bloomtextureheight = r_bloomstate.bloomheight;
8406 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
8407 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
8408 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
8409 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
8412 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))
8414 Cvar_SetValueQuick(&r_hdr, 0);
8415 Cvar_SetValueQuick(&r_bloom, 0);
8416 Cvar_SetValueQuick(&r_motionblur, 0);
8417 Cvar_SetValueQuick(&r_damageblur, 0);
8420 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)))
8421 screentexturewidth = screentextureheight = 0;
8422 if (!r_hdr.integer && !r_bloom.integer)
8423 bloomtexturewidth = bloomtextureheight = 0;
8425 // allocate textures as needed
8426 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
8428 if (r_bloomstate.texture_screen)
8429 R_FreeTexture(r_bloomstate.texture_screen);
8430 r_bloomstate.texture_screen = NULL;
8431 r_bloomstate.screentexturewidth = screentexturewidth;
8432 r_bloomstate.screentextureheight = screentextureheight;
8433 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
8434 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);
8436 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
8438 if (r_bloomstate.texture_bloom)
8439 R_FreeTexture(r_bloomstate.texture_bloom);
8440 r_bloomstate.texture_bloom = NULL;
8441 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
8442 r_bloomstate.bloomtextureheight = bloomtextureheight;
8443 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
8444 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);
8447 // when doing a reduced render (HDR) we want to use a smaller area
8448 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
8449 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
8450 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
8451 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
8452 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
8454 // set up a texcoord array for the full resolution screen image
8455 // (we have to keep this around to copy back during final render)
8456 r_bloomstate.screentexcoord2f[0] = 0;
8457 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
8458 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
8459 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
8460 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
8461 r_bloomstate.screentexcoord2f[5] = 0;
8462 r_bloomstate.screentexcoord2f[6] = 0;
8463 r_bloomstate.screentexcoord2f[7] = 0;
8465 // set up a texcoord array for the reduced resolution bloom image
8466 // (which will be additive blended over the screen image)
8467 r_bloomstate.bloomtexcoord2f[0] = 0;
8468 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8469 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8470 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8471 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8472 r_bloomstate.bloomtexcoord2f[5] = 0;
8473 r_bloomstate.bloomtexcoord2f[6] = 0;
8474 r_bloomstate.bloomtexcoord2f[7] = 0;
8476 switch(vid.renderpath)
8478 case RENDERPATH_GL11:
8479 case RENDERPATH_GL13:
8480 case RENDERPATH_GL20:
8481 case RENDERPATH_SOFT:
8482 case RENDERPATH_GLES2:
8484 case RENDERPATH_D3D9:
8485 case RENDERPATH_D3D10:
8486 case RENDERPATH_D3D11:
8489 for (i = 0;i < 4;i++)
8491 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
8492 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
8493 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
8494 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
8500 if (r_hdr.integer || r_bloom.integer)
8502 r_bloomstate.enabled = true;
8503 r_bloomstate.hdr = r_hdr.integer != 0;
8506 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);
8509 void R_Bloom_CopyBloomTexture(float colorscale)
8511 r_refdef.stats.bloom++;
8513 // scale down screen texture to the bloom texture size
8515 R_SetViewport(&r_bloomstate.viewport);
8516 GL_BlendFunc(GL_ONE, GL_ZERO);
8517 GL_Color(colorscale, colorscale, colorscale, 1);
8518 // 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...
8519 switch(vid.renderpath)
8521 case RENDERPATH_GL11:
8522 case RENDERPATH_GL13:
8523 case RENDERPATH_GL20:
8524 case RENDERPATH_SOFT:
8525 case RENDERPATH_GLES2:
8526 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8528 case RENDERPATH_D3D9:
8529 case RENDERPATH_D3D10:
8530 case RENDERPATH_D3D11:
8531 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8534 // TODO: do boxfilter scale-down in shader?
8535 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
8536 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8537 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8539 // we now have a bloom image in the framebuffer
8540 // copy it into the bloom image texture for later processing
8541 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);
8542 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8545 void R_Bloom_CopyHDRTexture(void)
8547 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);
8548 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8551 void R_Bloom_MakeTexture(void)
8554 float xoffset, yoffset, r, brighten;
8556 r_refdef.stats.bloom++;
8558 R_ResetViewRendering2D();
8560 // we have a bloom image in the framebuffer
8562 R_SetViewport(&r_bloomstate.viewport);
8564 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
8567 r = bound(0, r_bloom_colorexponent.value / x, 1);
8568 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
8570 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
8571 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
8572 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8573 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8575 // copy the vertically blurred bloom view to a texture
8576 R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
8577 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8580 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
8581 brighten = r_bloom_brighten.value;
8583 brighten *= r_hdr_range.value;
8584 brighten = sqrt(brighten);
8586 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
8587 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
8589 for (dir = 0;dir < 2;dir++)
8591 // blend on at multiple vertical offsets to achieve a vertical blur
8592 // TODO: do offset blends using GLSL
8593 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
8594 GL_BlendFunc(GL_ONE, GL_ZERO);
8595 for (x = -range;x <= range;x++)
8597 if (!dir){xoffset = 0;yoffset = x;}
8598 else {xoffset = x;yoffset = 0;}
8599 xoffset /= (float)r_bloomstate.bloomtexturewidth;
8600 yoffset /= (float)r_bloomstate.bloomtextureheight;
8601 // compute a texcoord array with the specified x and y offset
8602 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
8603 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8604 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8605 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8606 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8607 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
8608 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
8609 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
8610 // this r value looks like a 'dot' particle, fading sharply to
8611 // black at the edges
8612 // (probably not realistic but looks good enough)
8613 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
8614 //r = brighten/(range*2+1);
8615 r = brighten / (range * 2 + 1);
8617 r *= (1 - x*x/(float)(range*range));
8618 GL_Color(r, r, r, 1);
8619 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
8620 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8621 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8622 GL_BlendFunc(GL_ONE, GL_ONE);
8625 // copy the vertically blurred bloom view to a texture
8626 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);
8627 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8631 void R_HDR_RenderBloomTexture(void)
8633 int oldwidth, oldheight;
8634 float oldcolorscale;
8635 qboolean oldwaterstate;
8637 oldwaterstate = r_waterstate.enabled;
8638 oldcolorscale = r_refdef.view.colorscale;
8639 oldwidth = r_refdef.view.width;
8640 oldheight = r_refdef.view.height;
8641 r_refdef.view.width = r_bloomstate.bloomwidth;
8642 r_refdef.view.height = r_bloomstate.bloomheight;
8644 if(r_hdr.integer < 2)
8645 r_waterstate.enabled = false;
8647 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
8648 // TODO: add exposure compensation features
8649 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
8651 r_refdef.view.showdebug = false;
8652 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
8654 R_ResetViewRendering3D();
8656 R_ClearScreen(r_refdef.fogenabled);
8657 if (r_timereport_active)
8658 R_TimeReport("HDRclear");
8661 if (r_timereport_active)
8662 R_TimeReport("visibility");
8664 // only do secondary renders with HDR if r_hdr is 2 or higher
8665 r_waterstate.numwaterplanes = 0;
8666 if (r_waterstate.enabled)
8667 R_RenderWaterPlanes();
8669 r_refdef.view.showdebug = true;
8671 r_waterstate.numwaterplanes = 0;
8673 R_ResetViewRendering2D();
8675 R_Bloom_CopyHDRTexture();
8676 R_Bloom_MakeTexture();
8678 // restore the view settings
8679 r_waterstate.enabled = oldwaterstate;
8680 r_refdef.view.width = oldwidth;
8681 r_refdef.view.height = oldheight;
8682 r_refdef.view.colorscale = oldcolorscale;
8684 R_ResetViewRendering3D();
8686 R_ClearScreen(r_refdef.fogenabled);
8687 if (r_timereport_active)
8688 R_TimeReport("viewclear");
8691 static void R_BlendView(void)
8693 unsigned int permutation;
8694 float uservecs[4][4];
8696 switch (vid.renderpath)
8698 case RENDERPATH_GL20:
8699 case RENDERPATH_D3D9:
8700 case RENDERPATH_D3D10:
8701 case RENDERPATH_D3D11:
8702 case RENDERPATH_SOFT:
8703 case RENDERPATH_GLES2:
8705 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
8706 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
8707 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
8708 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
8709 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
8711 if (r_bloomstate.texture_screen)
8713 // make sure the buffer is available
8714 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
8716 R_ResetViewRendering2D();
8718 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
8720 // declare variables
8722 static float avgspeed;
8724 speed = VectorLength(cl.movement_velocity);
8726 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
8727 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
8729 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
8730 speed = bound(0, speed, 1);
8731 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
8733 // calculate values into a standard alpha
8734 cl.motionbluralpha = 1 - exp(-
8736 (r_motionblur.value * speed / 80)
8738 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
8741 max(0.0001, cl.time - cl.oldtime) // fps independent
8744 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
8745 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
8747 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
8749 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8750 GL_Color(1, 1, 1, cl.motionbluralpha);
8751 switch(vid.renderpath)
8753 case RENDERPATH_GL11:
8754 case RENDERPATH_GL13:
8755 case RENDERPATH_GL20:
8756 case RENDERPATH_SOFT:
8757 case RENDERPATH_GLES2:
8758 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8760 case RENDERPATH_D3D9:
8761 case RENDERPATH_D3D10:
8762 case RENDERPATH_D3D11:
8763 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8766 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
8767 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8768 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8772 // copy view into the screen texture
8773 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);
8774 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8776 else if (!r_bloomstate.texture_bloom)
8778 // we may still have to do view tint...
8779 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
8781 // apply a color tint to the whole view
8782 R_ResetViewRendering2D();
8783 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8784 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
8785 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8786 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8787 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8789 break; // no screen processing, no bloom, skip it
8792 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
8794 // render simple bloom effect
8795 // copy the screen and shrink it and darken it for the bloom process
8796 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
8797 // make the bloom texture
8798 R_Bloom_MakeTexture();
8801 #if _MSC_VER >= 1400
8802 #define sscanf sscanf_s
8804 memset(uservecs, 0, sizeof(uservecs));
8805 if (r_glsl_postprocess_uservec1_enable.integer)
8806 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
8807 if (r_glsl_postprocess_uservec2_enable.integer)
8808 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
8809 if (r_glsl_postprocess_uservec3_enable.integer)
8810 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
8811 if (r_glsl_postprocess_uservec4_enable.integer)
8812 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
8814 R_ResetViewRendering2D();
8815 GL_Color(1, 1, 1, 1);
8816 GL_BlendFunc(GL_ONE, GL_ZERO);
8818 switch(vid.renderpath)
8820 case RENDERPATH_GL20:
8821 case RENDERPATH_GLES2:
8822 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
8823 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
8824 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_bloomstate.texture_screen);
8825 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_bloomstate.texture_bloom );
8826 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
8827 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]);
8828 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
8829 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]);
8830 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]);
8831 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]);
8832 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]);
8833 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
8834 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
8835 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);
8837 case RENDERPATH_D3D9:
8839 // 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...
8840 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
8841 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
8842 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
8843 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
8844 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
8845 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8846 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
8847 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
8848 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
8849 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
8850 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
8851 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
8852 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
8853 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
8856 case RENDERPATH_D3D10:
8857 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
8859 case RENDERPATH_D3D11:
8860 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
8862 case RENDERPATH_SOFT:
8863 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
8864 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
8865 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
8866 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
8867 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
8868 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8869 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
8870 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
8871 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
8872 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
8873 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
8874 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
8875 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
8876 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
8881 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8882 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8884 case RENDERPATH_GL13:
8885 case RENDERPATH_GL11:
8886 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
8888 // apply a color tint to the whole view
8889 R_ResetViewRendering2D();
8890 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8891 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
8892 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8893 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8894 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8900 matrix4x4_t r_waterscrollmatrix;
8902 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
8904 if (r_refdef.fog_density)
8906 r_refdef.fogcolor[0] = r_refdef.fog_red;
8907 r_refdef.fogcolor[1] = r_refdef.fog_green;
8908 r_refdef.fogcolor[2] = r_refdef.fog_blue;
8910 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
8911 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
8912 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
8913 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
8917 VectorCopy(r_refdef.fogcolor, fogvec);
8918 // color.rgb *= ContrastBoost * SceneBrightness;
8919 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
8920 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
8921 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
8922 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
8927 void R_UpdateVariables(void)
8931 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
8933 r_refdef.farclip = r_farclip_base.value;
8934 if (r_refdef.scene.worldmodel)
8935 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
8936 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
8938 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
8939 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
8940 r_refdef.polygonfactor = 0;
8941 r_refdef.polygonoffset = 0;
8942 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
8943 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
8945 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
8946 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
8947 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
8948 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
8949 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
8950 if (FAKELIGHT_ENABLED)
8952 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
8954 if (r_showsurfaces.integer)
8956 r_refdef.scene.rtworld = false;
8957 r_refdef.scene.rtworldshadows = false;
8958 r_refdef.scene.rtdlight = false;
8959 r_refdef.scene.rtdlightshadows = false;
8960 r_refdef.lightmapintensity = 0;
8963 if (gamemode == GAME_NEHAHRA)
8965 if (gl_fogenable.integer)
8967 r_refdef.oldgl_fogenable = true;
8968 r_refdef.fog_density = gl_fogdensity.value;
8969 r_refdef.fog_red = gl_fogred.value;
8970 r_refdef.fog_green = gl_foggreen.value;
8971 r_refdef.fog_blue = gl_fogblue.value;
8972 r_refdef.fog_alpha = 1;
8973 r_refdef.fog_start = 0;
8974 r_refdef.fog_end = gl_skyclip.value;
8975 r_refdef.fog_height = 1<<30;
8976 r_refdef.fog_fadedepth = 128;
8978 else if (r_refdef.oldgl_fogenable)
8980 r_refdef.oldgl_fogenable = false;
8981 r_refdef.fog_density = 0;
8982 r_refdef.fog_red = 0;
8983 r_refdef.fog_green = 0;
8984 r_refdef.fog_blue = 0;
8985 r_refdef.fog_alpha = 0;
8986 r_refdef.fog_start = 0;
8987 r_refdef.fog_end = 0;
8988 r_refdef.fog_height = 1<<30;
8989 r_refdef.fog_fadedepth = 128;
8993 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
8994 r_refdef.fog_start = max(0, r_refdef.fog_start);
8995 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
8997 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
8999 if (r_refdef.fog_density && r_drawfog.integer)
9001 r_refdef.fogenabled = true;
9002 // this is the point where the fog reaches 0.9986 alpha, which we
9003 // consider a good enough cutoff point for the texture
9004 // (0.9986 * 256 == 255.6)
9005 if (r_fog_exp2.integer)
9006 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
9008 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
9009 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
9010 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
9011 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
9012 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
9013 R_BuildFogHeightTexture();
9014 // fog color was already set
9015 // update the fog texture
9016 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)
9017 R_BuildFogTexture();
9018 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
9019 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
9022 r_refdef.fogenabled = false;
9024 switch(vid.renderpath)
9026 case RENDERPATH_GL20:
9027 case RENDERPATH_D3D9:
9028 case RENDERPATH_D3D10:
9029 case RENDERPATH_D3D11:
9030 case RENDERPATH_SOFT:
9031 case RENDERPATH_GLES2:
9032 if(v_glslgamma.integer && !vid_gammatables_trivial)
9034 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
9036 // build GLSL gamma texture
9037 #define RAMPWIDTH 256
9038 unsigned short ramp[RAMPWIDTH * 3];
9039 unsigned char rampbgr[RAMPWIDTH][4];
9042 r_texture_gammaramps_serial = vid_gammatables_serial;
9044 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
9045 for(i = 0; i < RAMPWIDTH; ++i)
9047 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9048 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9049 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
9052 if (r_texture_gammaramps)
9054 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
9058 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
9064 // remove GLSL gamma texture
9067 case RENDERPATH_GL13:
9068 case RENDERPATH_GL11:
9073 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
9074 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
9080 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
9081 if( scenetype != r_currentscenetype ) {
9082 // store the old scenetype
9083 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
9084 r_currentscenetype = scenetype;
9085 // move in the new scene
9086 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
9095 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
9097 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
9098 if( scenetype == r_currentscenetype ) {
9099 return &r_refdef.scene;
9101 return &r_scenes_store[ scenetype ];
9110 int dpsoftrast_test;
9111 void R_RenderView(void)
9113 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
9115 dpsoftrast_test = r_test.integer;
9117 if (r_timereport_active)
9118 R_TimeReport("start");
9119 r_textureframe++; // used only by R_GetCurrentTexture
9120 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9122 if(R_CompileShader_CheckStaticParms())
9125 if (!r_drawentities.integer)
9126 r_refdef.scene.numentities = 0;
9128 R_AnimCache_ClearCache();
9129 R_FrameData_NewFrame();
9131 /* adjust for stereo display */
9132 if(R_Stereo_Active())
9134 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);
9135 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
9138 if (r_refdef.view.isoverlay)
9140 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
9141 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
9142 R_TimeReport("depthclear");
9144 r_refdef.view.showdebug = false;
9146 r_waterstate.enabled = false;
9147 r_waterstate.numwaterplanes = 0;
9151 r_refdef.view.matrix = originalmatrix;
9157 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
9159 r_refdef.view.matrix = originalmatrix;
9160 return; //Host_Error ("R_RenderView: NULL worldmodel");
9163 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
9165 R_RenderView_UpdateViewVectors();
9167 R_Shadow_UpdateWorldLightSelection();
9169 R_Bloom_StartFrame();
9170 R_Water_StartFrame();
9173 if (r_timereport_active)
9174 R_TimeReport("viewsetup");
9176 R_ResetViewRendering3D();
9178 if (r_refdef.view.clear || r_refdef.fogenabled)
9180 R_ClearScreen(r_refdef.fogenabled);
9181 if (r_timereport_active)
9182 R_TimeReport("viewclear");
9184 r_refdef.view.clear = true;
9186 // this produces a bloom texture to be used in R_BlendView() later
9187 if (r_hdr.integer && r_bloomstate.bloomwidth)
9189 R_HDR_RenderBloomTexture();
9190 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
9191 r_textureframe++; // used only by R_GetCurrentTexture
9194 r_refdef.view.showdebug = true;
9197 if (r_timereport_active)
9198 R_TimeReport("visibility");
9200 r_waterstate.numwaterplanes = 0;
9201 if (r_waterstate.enabled)
9202 R_RenderWaterPlanes();
9205 r_waterstate.numwaterplanes = 0;
9208 if (r_timereport_active)
9209 R_TimeReport("blendview");
9211 GL_Scissor(0, 0, vid.width, vid.height);
9212 GL_ScissorTest(false);
9214 r_refdef.view.matrix = originalmatrix;
9219 void R_RenderWaterPlanes(void)
9221 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
9223 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
9224 if (r_timereport_active)
9225 R_TimeReport("waterworld");
9228 // don't let sound skip if going slow
9229 if (r_refdef.scene.extraupdate)
9232 R_DrawModelsAddWaterPlanes();
9233 if (r_timereport_active)
9234 R_TimeReport("watermodels");
9236 if (r_waterstate.numwaterplanes)
9238 R_Water_ProcessPlanes();
9239 if (r_timereport_active)
9240 R_TimeReport("waterscenes");
9244 extern void R_DrawLightningBeams (void);
9245 extern void VM_CL_AddPolygonsToMeshQueue (void);
9246 extern void R_DrawPortals (void);
9247 extern cvar_t cl_locs_show;
9248 static void R_DrawLocs(void);
9249 static void R_DrawEntityBBoxes(void);
9250 static void R_DrawModelDecals(void);
9251 extern void R_DrawModelShadows(void);
9252 extern void R_DrawModelShadowMaps(void);
9253 extern cvar_t cl_decals_newsystem;
9254 extern qboolean r_shadow_usingdeferredprepass;
9255 void R_RenderScene(void)
9257 qboolean shadowmapping = false;
9259 if (r_timereport_active)
9260 R_TimeReport("beginscene");
9262 r_refdef.stats.renders++;
9266 // don't let sound skip if going slow
9267 if (r_refdef.scene.extraupdate)
9270 R_MeshQueue_BeginScene();
9274 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);
9276 if (r_timereport_active)
9277 R_TimeReport("skystartframe");
9279 if (cl.csqc_vidvars.drawworld)
9281 // don't let sound skip if going slow
9282 if (r_refdef.scene.extraupdate)
9285 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
9287 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
9288 if (r_timereport_active)
9289 R_TimeReport("worldsky");
9292 if (R_DrawBrushModelsSky() && r_timereport_active)
9293 R_TimeReport("bmodelsky");
9295 if (skyrendermasked && skyrenderlater)
9297 // we have to force off the water clipping plane while rendering sky
9301 if (r_timereport_active)
9302 R_TimeReport("sky");
9306 R_AnimCache_CacheVisibleEntities();
9307 if (r_timereport_active)
9308 R_TimeReport("animation");
9310 R_Shadow_PrepareLights();
9311 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
9312 R_Shadow_PrepareModelShadows();
9313 if (r_timereport_active)
9314 R_TimeReport("preparelights");
9316 if (R_Shadow_ShadowMappingEnabled())
9317 shadowmapping = true;
9319 if (r_shadow_usingdeferredprepass)
9320 R_Shadow_DrawPrepass();
9322 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
9324 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
9325 if (r_timereport_active)
9326 R_TimeReport("worlddepth");
9328 if (r_depthfirst.integer >= 2)
9330 R_DrawModelsDepth();
9331 if (r_timereport_active)
9332 R_TimeReport("modeldepth");
9335 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
9337 R_DrawModelShadowMaps();
9338 R_ResetViewRendering3D();
9339 // don't let sound skip if going slow
9340 if (r_refdef.scene.extraupdate)
9344 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
9346 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
9347 if (r_timereport_active)
9348 R_TimeReport("world");
9351 // don't let sound skip if going slow
9352 if (r_refdef.scene.extraupdate)
9356 if (r_timereport_active)
9357 R_TimeReport("models");
9359 // don't let sound skip if going slow
9360 if (r_refdef.scene.extraupdate)
9363 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9365 R_DrawModelShadows();
9366 R_ResetViewRendering3D();
9367 // don't let sound skip if going slow
9368 if (r_refdef.scene.extraupdate)
9372 if (!r_shadow_usingdeferredprepass)
9374 R_Shadow_DrawLights();
9375 if (r_timereport_active)
9376 R_TimeReport("rtlights");
9379 // don't let sound skip if going slow
9380 if (r_refdef.scene.extraupdate)
9383 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9385 R_DrawModelShadows();
9386 R_ResetViewRendering3D();
9387 // don't let sound skip if going slow
9388 if (r_refdef.scene.extraupdate)
9392 if (cl.csqc_vidvars.drawworld)
9394 if (cl_decals_newsystem.integer)
9396 R_DrawModelDecals();
9397 if (r_timereport_active)
9398 R_TimeReport("modeldecals");
9403 if (r_timereport_active)
9404 R_TimeReport("decals");
9408 if (r_timereport_active)
9409 R_TimeReport("particles");
9412 if (r_timereport_active)
9413 R_TimeReport("explosions");
9415 R_DrawLightningBeams();
9416 if (r_timereport_active)
9417 R_TimeReport("lightning");
9420 VM_CL_AddPolygonsToMeshQueue();
9422 if (r_refdef.view.showdebug)
9424 if (cl_locs_show.integer)
9427 if (r_timereport_active)
9428 R_TimeReport("showlocs");
9431 if (r_drawportals.integer)
9434 if (r_timereport_active)
9435 R_TimeReport("portals");
9438 if (r_showbboxes.value > 0)
9440 R_DrawEntityBBoxes();
9441 if (r_timereport_active)
9442 R_TimeReport("bboxes");
9446 R_MeshQueue_RenderTransparent();
9447 if (r_timereport_active)
9448 R_TimeReport("drawtrans");
9450 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))
9452 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
9453 if (r_timereport_active)
9454 R_TimeReport("worlddebug");
9455 R_DrawModelsDebug();
9456 if (r_timereport_active)
9457 R_TimeReport("modeldebug");
9460 if (cl.csqc_vidvars.drawworld)
9462 R_Shadow_DrawCoronas();
9463 if (r_timereport_active)
9464 R_TimeReport("coronas");
9469 GL_DepthTest(false);
9470 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
9471 GL_Color(1, 1, 1, 1);
9472 qglBegin(GL_POLYGON);
9473 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
9474 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
9475 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
9476 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
9478 qglBegin(GL_POLYGON);
9479 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]);
9480 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]);
9481 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]);
9482 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]);
9484 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
9488 // don't let sound skip if going slow
9489 if (r_refdef.scene.extraupdate)
9492 R_ResetViewRendering2D();
9495 static const unsigned short bboxelements[36] =
9505 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
9508 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
9510 RSurf_ActiveWorldEntity();
9512 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9513 GL_DepthMask(false);
9514 GL_DepthRange(0, 1);
9515 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
9516 // R_Mesh_ResetTextureState();
9518 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
9519 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
9520 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
9521 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
9522 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
9523 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
9524 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
9525 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
9526 R_FillColors(color4f, 8, cr, cg, cb, ca);
9527 if (r_refdef.fogenabled)
9529 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
9531 f1 = RSurf_FogVertex(v);
9533 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
9534 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
9535 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
9538 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
9539 R_Mesh_ResetTextureState();
9540 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9541 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
9544 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9548 prvm_edict_t *edict;
9549 prvm_prog_t *prog_save = prog;
9551 // this function draws bounding boxes of server entities
9555 GL_CullFace(GL_NONE);
9556 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9560 for (i = 0;i < numsurfaces;i++)
9562 edict = PRVM_EDICT_NUM(surfacelist[i]);
9563 switch ((int)edict->fields.server->solid)
9565 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
9566 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
9567 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
9568 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
9569 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
9570 default: Vector4Set(color, 0, 0, 0, 0.50);break;
9572 color[3] *= r_showbboxes.value;
9573 color[3] = bound(0, color[3], 1);
9574 GL_DepthTest(!r_showdisabledepthtest.integer);
9575 GL_CullFace(r_refdef.view.cullface_front);
9576 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
9582 static void R_DrawEntityBBoxes(void)
9585 prvm_edict_t *edict;
9587 prvm_prog_t *prog_save = prog;
9589 // this function draws bounding boxes of server entities
9595 for (i = 0;i < prog->num_edicts;i++)
9597 edict = PRVM_EDICT_NUM(i);
9598 if (edict->priv.server->free)
9600 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
9601 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
9603 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
9605 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
9606 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
9612 static const int nomodelelement3i[24] =
9624 static const unsigned short nomodelelement3s[24] =
9636 static const float nomodelvertex3f[6*3] =
9646 static const float nomodelcolor4f[6*4] =
9648 0.0f, 0.0f, 0.5f, 1.0f,
9649 0.0f, 0.0f, 0.5f, 1.0f,
9650 0.0f, 0.5f, 0.0f, 1.0f,
9651 0.0f, 0.5f, 0.0f, 1.0f,
9652 0.5f, 0.0f, 0.0f, 1.0f,
9653 0.5f, 0.0f, 0.0f, 1.0f
9656 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9662 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);
9664 // this is only called once per entity so numsurfaces is always 1, and
9665 // surfacelist is always {0}, so this code does not handle batches
9667 if (rsurface.ent_flags & RENDER_ADDITIVE)
9669 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
9670 GL_DepthMask(false);
9672 else if (rsurface.colormod[3] < 1)
9674 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9675 GL_DepthMask(false);
9679 GL_BlendFunc(GL_ONE, GL_ZERO);
9682 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
9683 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
9684 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
9685 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
9686 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
9687 for (i = 0, c = color4f;i < 6;i++, c += 4)
9689 c[0] *= rsurface.colormod[0];
9690 c[1] *= rsurface.colormod[1];
9691 c[2] *= rsurface.colormod[2];
9692 c[3] *= rsurface.colormod[3];
9694 if (r_refdef.fogenabled)
9696 for (i = 0, c = color4f;i < 6;i++, c += 4)
9698 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
9700 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
9701 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
9702 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
9705 // R_Mesh_ResetTextureState();
9706 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9707 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
9708 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
9711 void R_DrawNoModel(entity_render_t *ent)
9714 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
9715 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
9716 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
9718 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
9721 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
9723 vec3_t right1, right2, diff, normal;
9725 VectorSubtract (org2, org1, normal);
9727 // calculate 'right' vector for start
9728 VectorSubtract (r_refdef.view.origin, org1, diff);
9729 CrossProduct (normal, diff, right1);
9730 VectorNormalize (right1);
9732 // calculate 'right' vector for end
9733 VectorSubtract (r_refdef.view.origin, org2, diff);
9734 CrossProduct (normal, diff, right2);
9735 VectorNormalize (right2);
9737 vert[ 0] = org1[0] + width * right1[0];
9738 vert[ 1] = org1[1] + width * right1[1];
9739 vert[ 2] = org1[2] + width * right1[2];
9740 vert[ 3] = org1[0] - width * right1[0];
9741 vert[ 4] = org1[1] - width * right1[1];
9742 vert[ 5] = org1[2] - width * right1[2];
9743 vert[ 6] = org2[0] - width * right2[0];
9744 vert[ 7] = org2[1] - width * right2[1];
9745 vert[ 8] = org2[2] - width * right2[2];
9746 vert[ 9] = org2[0] + width * right2[0];
9747 vert[10] = org2[1] + width * right2[1];
9748 vert[11] = org2[2] + width * right2[2];
9751 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)
9753 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
9754 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
9755 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
9756 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
9757 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
9758 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
9759 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
9760 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
9761 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
9762 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
9763 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
9764 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
9767 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
9772 VectorSet(v, x, y, z);
9773 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
9774 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
9776 if (i == mesh->numvertices)
9778 if (mesh->numvertices < mesh->maxvertices)
9780 VectorCopy(v, vertex3f);
9781 mesh->numvertices++;
9783 return mesh->numvertices;
9789 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
9793 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
9794 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
9795 e = mesh->element3i + mesh->numtriangles * 3;
9796 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
9798 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
9799 if (mesh->numtriangles < mesh->maxtriangles)
9804 mesh->numtriangles++;
9806 element[1] = element[2];
9810 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
9814 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
9815 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
9816 e = mesh->element3i + mesh->numtriangles * 3;
9817 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
9819 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
9820 if (mesh->numtriangles < mesh->maxtriangles)
9825 mesh->numtriangles++;
9827 element[1] = element[2];
9831 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
9832 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
9834 int planenum, planenum2;
9837 mplane_t *plane, *plane2;
9839 double temppoints[2][256*3];
9840 // figure out how large a bounding box we need to properly compute this brush
9842 for (w = 0;w < numplanes;w++)
9843 maxdist = max(maxdist, fabs(planes[w].dist));
9844 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
9845 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
9846 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
9850 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
9851 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
9853 if (planenum2 == planenum)
9855 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);
9858 if (tempnumpoints < 3)
9860 // generate elements forming a triangle fan for this polygon
9861 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
9865 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)
9867 texturelayer_t *layer;
9868 layer = t->currentlayers + t->currentnumlayers++;
9870 layer->depthmask = depthmask;
9871 layer->blendfunc1 = blendfunc1;
9872 layer->blendfunc2 = blendfunc2;
9873 layer->texture = texture;
9874 layer->texmatrix = *matrix;
9875 layer->color[0] = r;
9876 layer->color[1] = g;
9877 layer->color[2] = b;
9878 layer->color[3] = a;
9881 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
9883 if(parms[0] == 0 && parms[1] == 0)
9885 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
9886 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
9891 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
9894 index = parms[2] + r_refdef.scene.time * parms[3];
9895 index -= floor(index);
9896 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
9899 case Q3WAVEFUNC_NONE:
9900 case Q3WAVEFUNC_NOISE:
9901 case Q3WAVEFUNC_COUNT:
9904 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
9905 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
9906 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
9907 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
9908 case Q3WAVEFUNC_TRIANGLE:
9910 f = index - floor(index);
9921 f = parms[0] + parms[1] * f;
9922 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
9923 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
9927 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
9932 matrix4x4_t matrix, temp;
9933 switch(tcmod->tcmod)
9937 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
9938 matrix = r_waterscrollmatrix;
9940 matrix = identitymatrix;
9942 case Q3TCMOD_ENTITYTRANSLATE:
9943 // this is used in Q3 to allow the gamecode to control texcoord
9944 // scrolling on the entity, which is not supported in darkplaces yet.
9945 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
9947 case Q3TCMOD_ROTATE:
9948 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
9949 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
9950 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
9953 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
9955 case Q3TCMOD_SCROLL:
9956 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
9958 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
9959 w = (int) tcmod->parms[0];
9960 h = (int) tcmod->parms[1];
9961 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
9963 idx = (int) floor(f * w * h);
9964 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
9966 case Q3TCMOD_STRETCH:
9967 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
9968 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
9970 case Q3TCMOD_TRANSFORM:
9971 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
9972 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
9973 VectorSet(tcmat + 6, 0 , 0 , 1);
9974 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
9975 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
9977 case Q3TCMOD_TURBULENT:
9978 // this is handled in the RSurf_PrepareVertices function
9979 matrix = identitymatrix;
9983 Matrix4x4_Concat(texmatrix, &matrix, &temp);
9986 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
9988 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
9989 char name[MAX_QPATH];
9990 skinframe_t *skinframe;
9991 unsigned char pixels[296*194];
9992 strlcpy(cache->name, skinname, sizeof(cache->name));
9993 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
9994 if (developer_loading.integer)
9995 Con_Printf("loading %s\n", name);
9996 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
9997 if (!skinframe || !skinframe->base)
10000 fs_offset_t filesize;
10002 f = FS_LoadFile(name, tempmempool, true, &filesize);
10005 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
10006 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
10010 cache->skinframe = skinframe;
10013 texture_t *R_GetCurrentTexture(texture_t *t)
10016 const entity_render_t *ent = rsurface.entity;
10017 dp_model_t *model = ent->model;
10018 q3shaderinfo_layer_tcmod_t *tcmod;
10020 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
10021 return t->currentframe;
10022 t->update_lastrenderframe = r_textureframe;
10023 t->update_lastrenderentity = (void *)ent;
10025 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
10026 t->camera_entity = ent->entitynumber;
10028 t->camera_entity = 0;
10030 // switch to an alternate material if this is a q1bsp animated material
10032 texture_t *texture = t;
10033 int s = rsurface.ent_skinnum;
10034 if ((unsigned int)s >= (unsigned int)model->numskins)
10036 if (model->skinscenes)
10038 if (model->skinscenes[s].framecount > 1)
10039 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
10041 s = model->skinscenes[s].firstframe;
10044 t = t + s * model->num_surfaces;
10047 // use an alternate animation if the entity's frame is not 0,
10048 // and only if the texture has an alternate animation
10049 if (rsurface.ent_alttextures && t->anim_total[1])
10050 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
10052 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
10054 texture->currentframe = t;
10057 // update currentskinframe to be a qw skin or animation frame
10058 if (rsurface.ent_qwskin >= 0)
10060 i = rsurface.ent_qwskin;
10061 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
10063 r_qwskincache_size = cl.maxclients;
10065 Mem_Free(r_qwskincache);
10066 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
10068 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
10069 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
10070 t->currentskinframe = r_qwskincache[i].skinframe;
10071 if (t->currentskinframe == NULL)
10072 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10074 else if (t->numskinframes >= 2)
10075 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10076 if (t->backgroundnumskinframes >= 2)
10077 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
10079 t->currentmaterialflags = t->basematerialflags;
10080 t->currentalpha = rsurface.colormod[3];
10081 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
10082 t->currentalpha *= r_wateralpha.value;
10083 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
10084 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
10085 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
10086 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
10087 if (!(rsurface.ent_flags & RENDER_LIGHT))
10088 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
10089 else if (FAKELIGHT_ENABLED)
10091 // no modellight if using fakelight for the map
10093 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10095 // pick a model lighting mode
10096 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
10097 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
10099 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
10101 if (rsurface.ent_flags & RENDER_ADDITIVE)
10102 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10103 else if (t->currentalpha < 1)
10104 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10105 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
10106 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
10107 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
10108 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
10109 if (t->backgroundnumskinframes)
10110 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
10111 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
10113 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
10114 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
10117 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
10118 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
10119 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
10121 // there is no tcmod
10122 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10124 t->currenttexmatrix = r_waterscrollmatrix;
10125 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
10127 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
10129 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
10130 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
10133 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10134 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
10135 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10136 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
10138 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
10139 if (t->currentskinframe->qpixels)
10140 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
10141 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
10142 if (!t->basetexture)
10143 t->basetexture = r_texture_notexture;
10144 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
10145 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
10146 t->nmaptexture = t->currentskinframe->nmap;
10147 if (!t->nmaptexture)
10148 t->nmaptexture = r_texture_blanknormalmap;
10149 t->glosstexture = r_texture_black;
10150 t->glowtexture = t->currentskinframe->glow;
10151 t->fogtexture = t->currentskinframe->fog;
10152 t->reflectmasktexture = t->currentskinframe->reflect;
10153 if (t->backgroundnumskinframes)
10155 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
10156 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
10157 t->backgroundglosstexture = r_texture_black;
10158 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
10159 if (!t->backgroundnmaptexture)
10160 t->backgroundnmaptexture = r_texture_blanknormalmap;
10164 t->backgroundbasetexture = r_texture_white;
10165 t->backgroundnmaptexture = r_texture_blanknormalmap;
10166 t->backgroundglosstexture = r_texture_black;
10167 t->backgroundglowtexture = NULL;
10169 t->specularpower = r_shadow_glossexponent.value;
10170 // TODO: store reference values for these in the texture?
10171 t->specularscale = 0;
10172 if (r_shadow_gloss.integer > 0)
10174 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
10176 if (r_shadow_glossintensity.value > 0)
10178 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
10179 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
10180 t->specularscale = r_shadow_glossintensity.value;
10183 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
10185 t->glosstexture = r_texture_white;
10186 t->backgroundglosstexture = r_texture_white;
10187 t->specularscale = r_shadow_gloss2intensity.value;
10188 t->specularpower = r_shadow_gloss2exponent.value;
10191 t->specularscale *= t->specularscalemod;
10192 t->specularpower *= t->specularpowermod;
10194 // lightmaps mode looks bad with dlights using actual texturing, so turn
10195 // off the colormap and glossmap, but leave the normalmap on as it still
10196 // accurately represents the shading involved
10197 if (gl_lightmaps.integer)
10199 t->basetexture = r_texture_grey128;
10200 t->pantstexture = r_texture_black;
10201 t->shirttexture = r_texture_black;
10202 t->nmaptexture = r_texture_blanknormalmap;
10203 t->glosstexture = r_texture_black;
10204 t->glowtexture = NULL;
10205 t->fogtexture = NULL;
10206 t->reflectmasktexture = NULL;
10207 t->backgroundbasetexture = NULL;
10208 t->backgroundnmaptexture = r_texture_blanknormalmap;
10209 t->backgroundglosstexture = r_texture_black;
10210 t->backgroundglowtexture = NULL;
10211 t->specularscale = 0;
10212 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
10215 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
10216 VectorClear(t->dlightcolor);
10217 t->currentnumlayers = 0;
10218 if (t->currentmaterialflags & MATERIALFLAG_WALL)
10220 int blendfunc1, blendfunc2;
10221 qboolean depthmask;
10222 if (t->currentmaterialflags & MATERIALFLAG_ADD)
10224 blendfunc1 = GL_SRC_ALPHA;
10225 blendfunc2 = GL_ONE;
10227 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
10229 blendfunc1 = GL_SRC_ALPHA;
10230 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
10232 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10234 blendfunc1 = t->customblendfunc[0];
10235 blendfunc2 = t->customblendfunc[1];
10239 blendfunc1 = GL_ONE;
10240 blendfunc2 = GL_ZERO;
10242 // don't colormod evilblend textures
10243 if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
10244 VectorSet(t->lightmapcolor, 1, 1, 1);
10245 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
10246 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10248 // fullbright is not affected by r_refdef.lightmapintensity
10249 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]);
10250 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10251 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]);
10252 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10253 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]);
10257 vec3_t ambientcolor;
10259 // set the color tint used for lights affecting this surface
10260 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
10262 // q3bsp has no lightmap updates, so the lightstylevalue that
10263 // would normally be baked into the lightmap must be
10264 // applied to the color
10265 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
10266 if (model->type == mod_brushq3)
10267 colorscale *= r_refdef.scene.rtlightstylevalue[0];
10268 colorscale *= r_refdef.lightmapintensity;
10269 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
10270 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
10271 // basic lit geometry
10272 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]);
10273 // add pants/shirt if needed
10274 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10275 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]);
10276 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10277 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]);
10278 // now add ambient passes if needed
10279 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
10281 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]);
10282 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10283 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]);
10284 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10285 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]);
10288 if (t->glowtexture != NULL && !gl_lightmaps.integer)
10289 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]);
10290 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
10292 // if this is opaque use alpha blend which will darken the earlier
10295 // if this is an alpha blended material, all the earlier passes
10296 // were darkened by fog already, so we only need to add the fog
10297 // color ontop through the fog mask texture
10299 // if this is an additive blended material, all the earlier passes
10300 // were darkened by fog already, and we should not add fog color
10301 // (because the background was not darkened, there is no fog color
10302 // that was lost behind it).
10303 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]);
10307 return t->currentframe;
10310 rsurfacestate_t rsurface;
10312 void RSurf_ActiveWorldEntity(void)
10314 dp_model_t *model = r_refdef.scene.worldmodel;
10315 //if (rsurface.entity == r_refdef.scene.worldentity)
10317 rsurface.entity = r_refdef.scene.worldentity;
10318 rsurface.skeleton = NULL;
10319 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
10320 rsurface.ent_skinnum = 0;
10321 rsurface.ent_qwskin = -1;
10322 rsurface.ent_shadertime = 0;
10323 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
10324 rsurface.matrix = identitymatrix;
10325 rsurface.inversematrix = identitymatrix;
10326 rsurface.matrixscale = 1;
10327 rsurface.inversematrixscale = 1;
10328 R_EntityMatrix(&identitymatrix);
10329 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
10330 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
10331 rsurface.fograngerecip = r_refdef.fograngerecip;
10332 rsurface.fogheightfade = r_refdef.fogheightfade;
10333 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
10334 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10335 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10336 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10337 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10338 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10339 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10340 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
10341 rsurface.colormod[3] = 1;
10342 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);
10343 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10344 rsurface.frameblend[0].lerp = 1;
10345 rsurface.ent_alttextures = false;
10346 rsurface.basepolygonfactor = r_refdef.polygonfactor;
10347 rsurface.basepolygonoffset = r_refdef.polygonoffset;
10348 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
10349 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10350 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10351 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10352 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10353 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10354 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10355 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10356 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10357 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
10358 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10359 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10360 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
10361 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10362 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10363 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
10364 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10365 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10366 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
10367 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10368 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10369 rsurface.modelelement3i = model->surfmesh.data_element3i;
10370 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10371 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10372 rsurface.modelelement3s = model->surfmesh.data_element3s;
10373 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10374 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10375 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10376 rsurface.modelnumvertices = model->surfmesh.num_vertices;
10377 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10378 rsurface.modelsurfaces = model->data_surfaces;
10379 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10380 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10381 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
10382 rsurface.modelgeneratedvertex = false;
10383 rsurface.batchgeneratedvertex = false;
10384 rsurface.batchfirstvertex = 0;
10385 rsurface.batchnumvertices = 0;
10386 rsurface.batchfirsttriangle = 0;
10387 rsurface.batchnumtriangles = 0;
10388 rsurface.batchvertex3f = NULL;
10389 rsurface.batchvertex3f_vertexbuffer = NULL;
10390 rsurface.batchvertex3f_bufferoffset = 0;
10391 rsurface.batchsvector3f = NULL;
10392 rsurface.batchsvector3f_vertexbuffer = NULL;
10393 rsurface.batchsvector3f_bufferoffset = 0;
10394 rsurface.batchtvector3f = NULL;
10395 rsurface.batchtvector3f_vertexbuffer = NULL;
10396 rsurface.batchtvector3f_bufferoffset = 0;
10397 rsurface.batchnormal3f = NULL;
10398 rsurface.batchnormal3f_vertexbuffer = NULL;
10399 rsurface.batchnormal3f_bufferoffset = 0;
10400 rsurface.batchlightmapcolor4f = NULL;
10401 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10402 rsurface.batchlightmapcolor4f_bufferoffset = 0;
10403 rsurface.batchtexcoordtexture2f = NULL;
10404 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10405 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10406 rsurface.batchtexcoordlightmap2f = NULL;
10407 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10408 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10409 rsurface.batchvertexmesh = NULL;
10410 rsurface.batchvertexmeshbuffer = NULL;
10411 rsurface.batchvertex3fbuffer = NULL;
10412 rsurface.batchelement3i = NULL;
10413 rsurface.batchelement3i_indexbuffer = NULL;
10414 rsurface.batchelement3i_bufferoffset = 0;
10415 rsurface.batchelement3s = NULL;
10416 rsurface.batchelement3s_indexbuffer = NULL;
10417 rsurface.batchelement3s_bufferoffset = 0;
10418 rsurface.passcolor4f = NULL;
10419 rsurface.passcolor4f_vertexbuffer = NULL;
10420 rsurface.passcolor4f_bufferoffset = 0;
10423 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
10425 dp_model_t *model = ent->model;
10426 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
10428 rsurface.entity = (entity_render_t *)ent;
10429 rsurface.skeleton = ent->skeleton;
10430 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
10431 rsurface.ent_skinnum = ent->skinnum;
10432 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;
10433 rsurface.ent_shadertime = ent->shadertime;
10434 rsurface.ent_flags = ent->flags;
10435 rsurface.matrix = ent->matrix;
10436 rsurface.inversematrix = ent->inversematrix;
10437 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10438 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10439 R_EntityMatrix(&rsurface.matrix);
10440 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10441 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10442 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10443 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10444 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10445 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10446 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
10447 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
10448 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
10449 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
10450 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
10451 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
10452 rsurface.colormod[3] = ent->alpha;
10453 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
10454 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
10455 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
10456 rsurface.basepolygonfactor = r_refdef.polygonfactor;
10457 rsurface.basepolygonoffset = r_refdef.polygonoffset;
10458 if (ent->model->brush.submodel && !prepass)
10460 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
10461 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
10463 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
10465 if (ent->animcache_vertex3f)
10467 rsurface.modelvertex3f = ent->animcache_vertex3f;
10468 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
10469 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
10470 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
10471 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
10472 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
10473 rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
10475 else if (wanttangents)
10477 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10478 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10479 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10480 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10481 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
10482 rsurface.modelvertexmesh = NULL;
10483 rsurface.modelvertexmeshbuffer = NULL;
10484 rsurface.modelvertex3fbuffer = NULL;
10486 else if (wantnormals)
10488 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10489 rsurface.modelsvector3f = NULL;
10490 rsurface.modeltvector3f = NULL;
10491 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10492 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
10493 rsurface.modelvertexmesh = NULL;
10494 rsurface.modelvertexmeshbuffer = NULL;
10495 rsurface.modelvertex3fbuffer = NULL;
10499 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10500 rsurface.modelsvector3f = NULL;
10501 rsurface.modeltvector3f = NULL;
10502 rsurface.modelnormal3f = NULL;
10503 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
10504 rsurface.modelvertexmesh = NULL;
10505 rsurface.modelvertexmeshbuffer = NULL;
10506 rsurface.modelvertex3fbuffer = NULL;
10508 rsurface.modelvertex3f_vertexbuffer = 0;
10509 rsurface.modelvertex3f_bufferoffset = 0;
10510 rsurface.modelsvector3f_vertexbuffer = 0;
10511 rsurface.modelsvector3f_bufferoffset = 0;
10512 rsurface.modeltvector3f_vertexbuffer = 0;
10513 rsurface.modeltvector3f_bufferoffset = 0;
10514 rsurface.modelnormal3f_vertexbuffer = 0;
10515 rsurface.modelnormal3f_bufferoffset = 0;
10516 rsurface.modelgeneratedvertex = true;
10520 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
10521 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10522 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10523 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10524 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10525 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10526 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10527 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10528 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10529 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
10530 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10531 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10532 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10533 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10534 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
10535 rsurface.modelgeneratedvertex = false;
10537 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
10538 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10539 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10540 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
10541 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10542 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10543 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
10544 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10545 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10546 rsurface.modelelement3i = model->surfmesh.data_element3i;
10547 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10548 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10549 rsurface.modelelement3s = model->surfmesh.data_element3s;
10550 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10551 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10552 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10553 rsurface.modelnumvertices = model->surfmesh.num_vertices;
10554 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10555 rsurface.modelsurfaces = model->data_surfaces;
10556 rsurface.batchgeneratedvertex = false;
10557 rsurface.batchfirstvertex = 0;
10558 rsurface.batchnumvertices = 0;
10559 rsurface.batchfirsttriangle = 0;
10560 rsurface.batchnumtriangles = 0;
10561 rsurface.batchvertex3f = NULL;
10562 rsurface.batchvertex3f_vertexbuffer = NULL;
10563 rsurface.batchvertex3f_bufferoffset = 0;
10564 rsurface.batchsvector3f = NULL;
10565 rsurface.batchsvector3f_vertexbuffer = NULL;
10566 rsurface.batchsvector3f_bufferoffset = 0;
10567 rsurface.batchtvector3f = NULL;
10568 rsurface.batchtvector3f_vertexbuffer = NULL;
10569 rsurface.batchtvector3f_bufferoffset = 0;
10570 rsurface.batchnormal3f = NULL;
10571 rsurface.batchnormal3f_vertexbuffer = NULL;
10572 rsurface.batchnormal3f_bufferoffset = 0;
10573 rsurface.batchlightmapcolor4f = NULL;
10574 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10575 rsurface.batchlightmapcolor4f_bufferoffset = 0;
10576 rsurface.batchtexcoordtexture2f = NULL;
10577 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10578 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10579 rsurface.batchtexcoordlightmap2f = NULL;
10580 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10581 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10582 rsurface.batchvertexmesh = NULL;
10583 rsurface.batchvertexmeshbuffer = NULL;
10584 rsurface.batchvertex3fbuffer = NULL;
10585 rsurface.batchelement3i = NULL;
10586 rsurface.batchelement3i_indexbuffer = NULL;
10587 rsurface.batchelement3i_bufferoffset = 0;
10588 rsurface.batchelement3s = NULL;
10589 rsurface.batchelement3s_indexbuffer = NULL;
10590 rsurface.batchelement3s_bufferoffset = 0;
10591 rsurface.passcolor4f = NULL;
10592 rsurface.passcolor4f_vertexbuffer = NULL;
10593 rsurface.passcolor4f_bufferoffset = 0;
10596 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)
10598 rsurface.entity = r_refdef.scene.worldentity;
10599 rsurface.skeleton = NULL;
10600 rsurface.ent_skinnum = 0;
10601 rsurface.ent_qwskin = -1;
10602 rsurface.ent_shadertime = shadertime;
10603 rsurface.ent_flags = entflags;
10604 rsurface.modelnumvertices = numvertices;
10605 rsurface.modelnumtriangles = numtriangles;
10606 rsurface.matrix = *matrix;
10607 rsurface.inversematrix = *inversematrix;
10608 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10609 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10610 R_EntityMatrix(&rsurface.matrix);
10611 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10612 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10613 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10614 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10615 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10616 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10617 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10618 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10619 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10620 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10621 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10622 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
10623 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);
10624 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10625 rsurface.frameblend[0].lerp = 1;
10626 rsurface.ent_alttextures = false;
10627 rsurface.basepolygonfactor = r_refdef.polygonfactor;
10628 rsurface.basepolygonoffset = r_refdef.polygonoffset;
10631 rsurface.modelvertex3f = (float *)vertex3f;
10632 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10633 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10634 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10636 else if (wantnormals)
10638 rsurface.modelvertex3f = (float *)vertex3f;
10639 rsurface.modelsvector3f = NULL;
10640 rsurface.modeltvector3f = NULL;
10641 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10645 rsurface.modelvertex3f = (float *)vertex3f;
10646 rsurface.modelsvector3f = NULL;
10647 rsurface.modeltvector3f = NULL;
10648 rsurface.modelnormal3f = NULL;
10650 rsurface.modelvertexmesh = NULL;
10651 rsurface.modelvertexmeshbuffer = NULL;
10652 rsurface.modelvertex3fbuffer = NULL;
10653 rsurface.modelvertex3f_vertexbuffer = 0;
10654 rsurface.modelvertex3f_bufferoffset = 0;
10655 rsurface.modelsvector3f_vertexbuffer = 0;
10656 rsurface.modelsvector3f_bufferoffset = 0;
10657 rsurface.modeltvector3f_vertexbuffer = 0;
10658 rsurface.modeltvector3f_bufferoffset = 0;
10659 rsurface.modelnormal3f_vertexbuffer = 0;
10660 rsurface.modelnormal3f_bufferoffset = 0;
10661 rsurface.modelgeneratedvertex = true;
10662 rsurface.modellightmapcolor4f = (float *)color4f;
10663 rsurface.modellightmapcolor4f_vertexbuffer = 0;
10664 rsurface.modellightmapcolor4f_bufferoffset = 0;
10665 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
10666 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
10667 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
10668 rsurface.modeltexcoordlightmap2f = NULL;
10669 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
10670 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
10671 rsurface.modelelement3i = (int *)element3i;
10672 rsurface.modelelement3i_indexbuffer = NULL;
10673 rsurface.modelelement3i_bufferoffset = 0;
10674 rsurface.modelelement3s = (unsigned short *)element3s;
10675 rsurface.modelelement3s_indexbuffer = NULL;
10676 rsurface.modelelement3s_bufferoffset = 0;
10677 rsurface.modellightmapoffsets = NULL;
10678 rsurface.modelsurfaces = NULL;
10679 rsurface.batchgeneratedvertex = false;
10680 rsurface.batchfirstvertex = 0;
10681 rsurface.batchnumvertices = 0;
10682 rsurface.batchfirsttriangle = 0;
10683 rsurface.batchnumtriangles = 0;
10684 rsurface.batchvertex3f = NULL;
10685 rsurface.batchvertex3f_vertexbuffer = NULL;
10686 rsurface.batchvertex3f_bufferoffset = 0;
10687 rsurface.batchsvector3f = NULL;
10688 rsurface.batchsvector3f_vertexbuffer = NULL;
10689 rsurface.batchsvector3f_bufferoffset = 0;
10690 rsurface.batchtvector3f = NULL;
10691 rsurface.batchtvector3f_vertexbuffer = NULL;
10692 rsurface.batchtvector3f_bufferoffset = 0;
10693 rsurface.batchnormal3f = NULL;
10694 rsurface.batchnormal3f_vertexbuffer = NULL;
10695 rsurface.batchnormal3f_bufferoffset = 0;
10696 rsurface.batchlightmapcolor4f = NULL;
10697 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10698 rsurface.batchlightmapcolor4f_bufferoffset = 0;
10699 rsurface.batchtexcoordtexture2f = NULL;
10700 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10701 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10702 rsurface.batchtexcoordlightmap2f = NULL;
10703 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10704 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10705 rsurface.batchvertexmesh = NULL;
10706 rsurface.batchvertexmeshbuffer = NULL;
10707 rsurface.batchvertex3fbuffer = NULL;
10708 rsurface.batchelement3i = NULL;
10709 rsurface.batchelement3i_indexbuffer = NULL;
10710 rsurface.batchelement3i_bufferoffset = 0;
10711 rsurface.batchelement3s = NULL;
10712 rsurface.batchelement3s_indexbuffer = NULL;
10713 rsurface.batchelement3s_bufferoffset = 0;
10714 rsurface.passcolor4f = NULL;
10715 rsurface.passcolor4f_vertexbuffer = NULL;
10716 rsurface.passcolor4f_bufferoffset = 0;
10718 if (rsurface.modelnumvertices && rsurface.modelelement3i)
10720 if ((wantnormals || wanttangents) && !normal3f)
10722 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10723 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
10725 if (wanttangents && !svector3f)
10727 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10728 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10729 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
10734 float RSurf_FogPoint(const float *v)
10736 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
10737 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
10738 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
10739 float FogHeightFade = r_refdef.fogheightfade;
10741 unsigned int fogmasktableindex;
10742 if (r_refdef.fogplaneviewabove)
10743 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
10745 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
10746 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
10747 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
10750 float RSurf_FogVertex(const float *v)
10752 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
10753 float FogPlaneViewDist = rsurface.fogplaneviewdist;
10754 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
10755 float FogHeightFade = rsurface.fogheightfade;
10757 unsigned int fogmasktableindex;
10758 if (r_refdef.fogplaneviewabove)
10759 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
10761 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
10762 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
10763 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
10766 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
10769 for (i = 0;i < numelements;i++)
10770 outelement3i[i] = inelement3i[i] + adjust;
10773 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
10774 extern cvar_t gl_vbo;
10775 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
10783 int surfacefirsttriangle;
10784 int surfacenumtriangles;
10785 int surfacefirstvertex;
10786 int surfaceendvertex;
10787 int surfacenumvertices;
10788 int batchnumvertices;
10789 int batchnumtriangles;
10793 qboolean dynamicvertex;
10797 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
10798 float waveparms[4];
10799 q3shaderinfo_deform_t *deform;
10800 const msurface_t *surface, *firstsurface;
10801 r_vertexmesh_t *vertexmesh;
10802 if (!texturenumsurfaces)
10804 // find vertex range of this surface batch
10806 firstsurface = texturesurfacelist[0];
10807 firsttriangle = firstsurface->num_firsttriangle;
10808 batchnumvertices = 0;
10809 batchnumtriangles = 0;
10810 firstvertex = endvertex = firstsurface->num_firstvertex;
10811 for (i = 0;i < texturenumsurfaces;i++)
10813 surface = texturesurfacelist[i];
10814 if (surface != firstsurface + i)
10816 surfacefirstvertex = surface->num_firstvertex;
10817 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
10818 surfacenumvertices = surface->num_vertices;
10819 surfacenumtriangles = surface->num_triangles;
10820 if (firstvertex > surfacefirstvertex)
10821 firstvertex = surfacefirstvertex;
10822 if (endvertex < surfaceendvertex)
10823 endvertex = surfaceendvertex;
10824 batchnumvertices += surfacenumvertices;
10825 batchnumtriangles += surfacenumtriangles;
10828 // we now know the vertex range used, and if there are any gaps in it
10829 rsurface.batchfirstvertex = firstvertex;
10830 rsurface.batchnumvertices = endvertex - firstvertex;
10831 rsurface.batchfirsttriangle = firsttriangle;
10832 rsurface.batchnumtriangles = batchnumtriangles;
10834 // this variable holds flags for which properties have been updated that
10835 // may require regenerating vertexmesh array...
10838 // check if any dynamic vertex processing must occur
10839 dynamicvertex = false;
10841 // if there is a chance of animated vertex colors, it's a dynamic batch
10842 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
10844 dynamicvertex = true;
10845 batchneed |= BATCHNEED_NOGAPS;
10846 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
10849 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
10851 switch (deform->deform)
10854 case Q3DEFORM_PROJECTIONSHADOW:
10855 case Q3DEFORM_TEXT0:
10856 case Q3DEFORM_TEXT1:
10857 case Q3DEFORM_TEXT2:
10858 case Q3DEFORM_TEXT3:
10859 case Q3DEFORM_TEXT4:
10860 case Q3DEFORM_TEXT5:
10861 case Q3DEFORM_TEXT6:
10862 case Q3DEFORM_TEXT7:
10863 case Q3DEFORM_NONE:
10865 case Q3DEFORM_AUTOSPRITE:
10866 dynamicvertex = true;
10867 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10868 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10870 case Q3DEFORM_AUTOSPRITE2:
10871 dynamicvertex = true;
10872 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10873 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10875 case Q3DEFORM_NORMAL:
10876 dynamicvertex = true;
10877 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10878 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10880 case Q3DEFORM_WAVE:
10881 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10882 break; // if wavefunc is a nop, ignore this transform
10883 dynamicvertex = true;
10884 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10885 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10887 case Q3DEFORM_BULGE:
10888 dynamicvertex = true;
10889 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10890 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10892 case Q3DEFORM_MOVE:
10893 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10894 break; // if wavefunc is a nop, ignore this transform
10895 dynamicvertex = true;
10896 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
10897 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
10901 switch(rsurface.texture->tcgen.tcgen)
10904 case Q3TCGEN_TEXTURE:
10906 case Q3TCGEN_LIGHTMAP:
10907 dynamicvertex = true;
10908 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
10909 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
10911 case Q3TCGEN_VECTOR:
10912 dynamicvertex = true;
10913 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
10914 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
10916 case Q3TCGEN_ENVIRONMENT:
10917 dynamicvertex = true;
10918 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
10919 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
10922 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10924 dynamicvertex = true;
10925 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10926 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
10929 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
10931 dynamicvertex = true;
10932 batchneed |= BATCHNEED_NOGAPS;
10933 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
10936 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
10938 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
10939 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
10940 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
10941 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
10942 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
10943 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
10944 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
10947 // when the model data has no vertex buffer (dynamic mesh), we need to
10949 if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
10950 batchneed |= BATCHNEED_NOGAPS;
10952 // if needsupdate, we have to do a dynamic vertex batch for sure
10953 if (needsupdate & batchneed)
10954 dynamicvertex = true;
10956 // see if we need to build vertexmesh from arrays
10957 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
10958 dynamicvertex = true;
10960 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
10961 // also some drivers strongly dislike firstvertex
10962 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
10963 dynamicvertex = true;
10965 rsurface.batchvertex3f = rsurface.modelvertex3f;
10966 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
10967 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
10968 rsurface.batchsvector3f = rsurface.modelsvector3f;
10969 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
10970 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
10971 rsurface.batchtvector3f = rsurface.modeltvector3f;
10972 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
10973 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
10974 rsurface.batchnormal3f = rsurface.modelnormal3f;
10975 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
10976 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
10977 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
10978 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
10979 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
10980 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
10981 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
10982 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
10983 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
10984 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
10985 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
10986 rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
10987 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
10988 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
10989 rsurface.batchelement3i = rsurface.modelelement3i;
10990 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
10991 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
10992 rsurface.batchelement3s = rsurface.modelelement3s;
10993 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
10994 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
10996 // if any dynamic vertex processing has to occur in software, we copy the
10997 // entire surface list together before processing to rebase the vertices
10998 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
11000 // if any gaps exist and we do not have a static vertex buffer, we have to
11001 // copy the surface list together to avoid wasting upload bandwidth on the
11002 // vertices in the gaps.
11004 // if gaps exist and we have a static vertex buffer, we still have to
11005 // combine the index buffer ranges into one dynamic index buffer.
11007 // in all cases we end up with data that can be drawn in one call.
11009 if (!dynamicvertex)
11011 // static vertex data, just set pointers...
11012 rsurface.batchgeneratedvertex = false;
11013 // if there are gaps, we want to build a combined index buffer,
11014 // otherwise use the original static buffer with an appropriate offset
11017 // build a new triangle elements array for this batch
11018 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
11019 rsurface.batchfirsttriangle = 0;
11021 for (i = 0;i < texturenumsurfaces;i++)
11023 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11024 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11025 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
11026 numtriangles += surfacenumtriangles;
11028 rsurface.batchelement3i_indexbuffer = NULL;
11029 rsurface.batchelement3i_bufferoffset = 0;
11030 rsurface.batchelement3s = NULL;
11031 rsurface.batchelement3s_indexbuffer = NULL;
11032 rsurface.batchelement3s_bufferoffset = 0;
11033 if (endvertex <= 65536)
11035 // make a 16bit (unsigned short) index array if possible
11036 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
11037 for (i = 0;i < numtriangles*3;i++)
11038 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
11044 // something needs software processing, do it for real...
11045 // we only directly handle separate array data in this case and then
11046 // generate interleaved data if needed...
11047 rsurface.batchgeneratedvertex = true;
11049 // now copy the vertex data into a combined array and make an index array
11050 // (this is what Quake3 does all the time)
11051 //if (gaps || rsurface.batchfirstvertex)
11053 rsurface.batchvertex3fbuffer = NULL;
11054 rsurface.batchvertexmesh = NULL;
11055 rsurface.batchvertexmeshbuffer = NULL;
11056 rsurface.batchvertex3f = NULL;
11057 rsurface.batchvertex3f_vertexbuffer = NULL;
11058 rsurface.batchvertex3f_bufferoffset = 0;
11059 rsurface.batchsvector3f = NULL;
11060 rsurface.batchsvector3f_vertexbuffer = NULL;
11061 rsurface.batchsvector3f_bufferoffset = 0;
11062 rsurface.batchtvector3f = NULL;
11063 rsurface.batchtvector3f_vertexbuffer = NULL;
11064 rsurface.batchtvector3f_bufferoffset = 0;
11065 rsurface.batchnormal3f = NULL;
11066 rsurface.batchnormal3f_vertexbuffer = NULL;
11067 rsurface.batchnormal3f_bufferoffset = 0;
11068 rsurface.batchlightmapcolor4f = NULL;
11069 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11070 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11071 rsurface.batchtexcoordtexture2f = NULL;
11072 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11073 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11074 rsurface.batchtexcoordlightmap2f = NULL;
11075 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11076 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11077 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
11078 rsurface.batchelement3i_indexbuffer = NULL;
11079 rsurface.batchelement3i_bufferoffset = 0;
11080 rsurface.batchelement3s = NULL;
11081 rsurface.batchelement3s_indexbuffer = NULL;
11082 rsurface.batchelement3s_bufferoffset = 0;
11083 // we'll only be setting up certain arrays as needed
11084 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11085 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
11086 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11087 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11088 if (batchneed & BATCHNEED_ARRAY_NORMAL)
11089 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11090 if (batchneed & BATCHNEED_ARRAY_VECTOR)
11092 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11093 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11095 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
11096 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
11097 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
11098 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11099 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
11100 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11103 for (i = 0;i < texturenumsurfaces;i++)
11105 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
11106 surfacenumvertices = texturesurfacelist[i]->num_vertices;
11107 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11108 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11109 // copy only the data requested
11110 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
11111 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
11112 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
11114 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11115 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11116 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
11117 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11118 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
11120 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11121 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11123 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
11124 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
11125 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
11126 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11127 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
11128 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11130 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
11131 numvertices += surfacenumvertices;
11132 numtriangles += surfacenumtriangles;
11135 // generate a 16bit index array as well if possible
11136 // (in general, dynamic batches fit)
11137 if (numvertices <= 65536)
11139 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
11140 for (i = 0;i < numtriangles*3;i++)
11141 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
11144 // since we've copied everything, the batch now starts at 0
11145 rsurface.batchfirstvertex = 0;
11146 rsurface.batchnumvertices = batchnumvertices;
11147 rsurface.batchfirsttriangle = 0;
11148 rsurface.batchnumtriangles = batchnumtriangles;
11151 // q1bsp surfaces rendered in vertex color mode have to have colors
11152 // calculated based on lightstyles
11153 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11155 // generate color arrays for the surfaces in this list
11159 const int *offsets;
11160 const unsigned char *lm;
11161 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
11162 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11163 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11165 for (i = 0;i < texturenumsurfaces;i++)
11167 surface = texturesurfacelist[i];
11168 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
11169 surfacenumvertices = surface->num_vertices;
11170 if (surface->lightmapinfo->samples)
11172 for (j = 0;j < surfacenumvertices;j++)
11174 lm = surface->lightmapinfo->samples + offsets[j];
11175 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
11176 VectorScale(lm, scale, c);
11177 if (surface->lightmapinfo->styles[1] != 255)
11179 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
11181 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
11182 VectorMA(c, scale, lm, c);
11183 if (surface->lightmapinfo->styles[2] != 255)
11186 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
11187 VectorMA(c, scale, lm, c);
11188 if (surface->lightmapinfo->styles[3] != 255)
11191 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
11192 VectorMA(c, scale, lm, c);
11199 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);
11205 for (j = 0;j < surfacenumvertices;j++)
11207 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
11214 // if vertices are deformed (sprite flares and things in maps, possibly
11215 // water waves, bulges and other deformations), modify the copied vertices
11217 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11219 switch (deform->deform)
11222 case Q3DEFORM_PROJECTIONSHADOW:
11223 case Q3DEFORM_TEXT0:
11224 case Q3DEFORM_TEXT1:
11225 case Q3DEFORM_TEXT2:
11226 case Q3DEFORM_TEXT3:
11227 case Q3DEFORM_TEXT4:
11228 case Q3DEFORM_TEXT5:
11229 case Q3DEFORM_TEXT6:
11230 case Q3DEFORM_TEXT7:
11231 case Q3DEFORM_NONE:
11233 case Q3DEFORM_AUTOSPRITE:
11234 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11235 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11236 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11237 VectorNormalize(newforward);
11238 VectorNormalize(newright);
11239 VectorNormalize(newup);
11240 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11241 // rsurface.batchvertex3f_vertexbuffer = NULL;
11242 // rsurface.batchvertex3f_bufferoffset = 0;
11243 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
11244 // rsurface.batchsvector3f_vertexbuffer = NULL;
11245 // rsurface.batchsvector3f_bufferoffset = 0;
11246 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
11247 // rsurface.batchtvector3f_vertexbuffer = NULL;
11248 // rsurface.batchtvector3f_bufferoffset = 0;
11249 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
11250 // rsurface.batchnormal3f_vertexbuffer = NULL;
11251 // rsurface.batchnormal3f_bufferoffset = 0;
11252 // a single autosprite surface can contain multiple sprites...
11253 for (j = 0;j < batchnumvertices - 3;j += 4)
11255 VectorClear(center);
11256 for (i = 0;i < 4;i++)
11257 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11258 VectorScale(center, 0.25f, center);
11259 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
11260 VectorCopy(rsurface.batchsvector3f + 3*j, right);
11261 VectorCopy(rsurface.batchtvector3f + 3*j, up);
11262 for (i = 0;i < 4;i++)
11264 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
11265 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
11268 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
11269 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11270 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);
11272 case Q3DEFORM_AUTOSPRITE2:
11273 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11274 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11275 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11276 VectorNormalize(newforward);
11277 VectorNormalize(newright);
11278 VectorNormalize(newup);
11279 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11280 // rsurface.batchvertex3f_vertexbuffer = NULL;
11281 // rsurface.batchvertex3f_bufferoffset = 0;
11283 const float *v1, *v2;
11293 memset(shortest, 0, sizeof(shortest));
11294 // a single autosprite surface can contain multiple sprites...
11295 for (j = 0;j < batchnumvertices - 3;j += 4)
11297 VectorClear(center);
11298 for (i = 0;i < 4;i++)
11299 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11300 VectorScale(center, 0.25f, center);
11301 // find the two shortest edges, then use them to define the
11302 // axis vectors for rotating around the central axis
11303 for (i = 0;i < 6;i++)
11305 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
11306 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
11307 l = VectorDistance2(v1, v2);
11308 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
11309 if (v1[2] != v2[2])
11310 l += (1.0f / 1024.0f);
11311 if (shortest[0].length2 > l || i == 0)
11313 shortest[1] = shortest[0];
11314 shortest[0].length2 = l;
11315 shortest[0].v1 = v1;
11316 shortest[0].v2 = v2;
11318 else if (shortest[1].length2 > l || i == 1)
11320 shortest[1].length2 = l;
11321 shortest[1].v1 = v1;
11322 shortest[1].v2 = v2;
11325 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
11326 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
11327 // this calculates the right vector from the shortest edge
11328 // and the up vector from the edge midpoints
11329 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
11330 VectorNormalize(right);
11331 VectorSubtract(end, start, up);
11332 VectorNormalize(up);
11333 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
11334 VectorSubtract(rsurface.localvieworigin, center, forward);
11335 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
11336 VectorNegate(forward, forward);
11337 VectorReflect(forward, 0, up, forward);
11338 VectorNormalize(forward);
11339 CrossProduct(up, forward, newright);
11340 VectorNormalize(newright);
11341 // rotate the quad around the up axis vector, this is made
11342 // especially easy by the fact we know the quad is flat,
11343 // so we only have to subtract the center position and
11344 // measure distance along the right vector, and then
11345 // multiply that by the newright vector and add back the
11347 // we also need to subtract the old position to undo the
11348 // displacement from the center, which we do with a
11349 // DotProduct, the subtraction/addition of center is also
11350 // optimized into DotProducts here
11351 l = DotProduct(right, center);
11352 for (i = 0;i < 4;i++)
11354 v1 = rsurface.batchvertex3f + 3*(j+i);
11355 f = DotProduct(right, v1) - l;
11356 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
11360 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
11362 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11363 // rsurface.batchnormal3f_vertexbuffer = NULL;
11364 // rsurface.batchnormal3f_bufferoffset = 0;
11365 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11367 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11369 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11370 // rsurface.batchsvector3f_vertexbuffer = NULL;
11371 // rsurface.batchsvector3f_bufferoffset = 0;
11372 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11373 // rsurface.batchtvector3f_vertexbuffer = NULL;
11374 // rsurface.batchtvector3f_bufferoffset = 0;
11375 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);
11378 case Q3DEFORM_NORMAL:
11379 // deform the normals to make reflections wavey
11380 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
11381 rsurface.batchnormal3f_vertexbuffer = NULL;
11382 rsurface.batchnormal3f_bufferoffset = 0;
11383 for (j = 0;j < batchnumvertices;j++)
11386 float *normal = rsurface.batchnormal3f + 3*j;
11387 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
11388 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
11389 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]);
11390 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]);
11391 VectorNormalize(normal);
11393 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11395 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11396 // rsurface.batchsvector3f_vertexbuffer = NULL;
11397 // rsurface.batchsvector3f_bufferoffset = 0;
11398 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11399 // rsurface.batchtvector3f_vertexbuffer = NULL;
11400 // rsurface.batchtvector3f_bufferoffset = 0;
11401 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);
11404 case Q3DEFORM_WAVE:
11405 // deform vertex array to make wavey water and flags and such
11406 waveparms[0] = deform->waveparms[0];
11407 waveparms[1] = deform->waveparms[1];
11408 waveparms[2] = deform->waveparms[2];
11409 waveparms[3] = deform->waveparms[3];
11410 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
11411 break; // if wavefunc is a nop, don't make a dynamic vertex array
11412 // this is how a divisor of vertex influence on deformation
11413 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
11414 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11415 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11416 // rsurface.batchvertex3f_vertexbuffer = NULL;
11417 // rsurface.batchvertex3f_bufferoffset = 0;
11418 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
11419 // rsurface.batchnormal3f_vertexbuffer = NULL;
11420 // rsurface.batchnormal3f_bufferoffset = 0;
11421 for (j = 0;j < batchnumvertices;j++)
11423 // if the wavefunc depends on time, evaluate it per-vertex
11426 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
11427 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11429 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
11431 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
11432 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11433 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11435 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11436 // rsurface.batchsvector3f_vertexbuffer = NULL;
11437 // rsurface.batchsvector3f_bufferoffset = 0;
11438 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11439 // rsurface.batchtvector3f_vertexbuffer = NULL;
11440 // rsurface.batchtvector3f_bufferoffset = 0;
11441 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);
11444 case Q3DEFORM_BULGE:
11445 // deform vertex array to make the surface have moving bulges
11446 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11447 // rsurface.batchvertex3f_vertexbuffer = NULL;
11448 // rsurface.batchvertex3f_bufferoffset = 0;
11449 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
11450 // rsurface.batchnormal3f_vertexbuffer = NULL;
11451 // rsurface.batchnormal3f_bufferoffset = 0;
11452 for (j = 0;j < batchnumvertices;j++)
11454 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
11455 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
11457 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
11458 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11459 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11461 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11462 // rsurface.batchsvector3f_vertexbuffer = NULL;
11463 // rsurface.batchsvector3f_bufferoffset = 0;
11464 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11465 // rsurface.batchtvector3f_vertexbuffer = NULL;
11466 // rsurface.batchtvector3f_bufferoffset = 0;
11467 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);
11470 case Q3DEFORM_MOVE:
11471 // deform vertex array
11472 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11473 break; // if wavefunc is a nop, don't make a dynamic vertex array
11474 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
11475 VectorScale(deform->parms, scale, waveparms);
11476 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11477 // rsurface.batchvertex3f_vertexbuffer = NULL;
11478 // rsurface.batchvertex3f_bufferoffset = 0;
11479 for (j = 0;j < batchnumvertices;j++)
11480 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
11485 // generate texcoords based on the chosen texcoord source
11486 switch(rsurface.texture->tcgen.tcgen)
11489 case Q3TCGEN_TEXTURE:
11491 case Q3TCGEN_LIGHTMAP:
11492 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11493 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11494 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11495 if (rsurface.batchtexcoordlightmap2f)
11496 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
11498 case Q3TCGEN_VECTOR:
11499 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11500 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11501 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11502 for (j = 0;j < batchnumvertices;j++)
11504 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
11505 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
11508 case Q3TCGEN_ENVIRONMENT:
11509 // make environment reflections using a spheremap
11510 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11511 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11512 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11513 for (j = 0;j < batchnumvertices;j++)
11515 // identical to Q3A's method, but executed in worldspace so
11516 // carried models can be shiny too
11518 float viewer[3], d, reflected[3], worldreflected[3];
11520 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
11521 // VectorNormalize(viewer);
11523 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
11525 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
11526 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
11527 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
11528 // note: this is proportinal to viewer, so we can normalize later
11530 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
11531 VectorNormalize(worldreflected);
11533 // note: this sphere map only uses world x and z!
11534 // so positive and negative y will LOOK THE SAME.
11535 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
11536 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
11540 // the only tcmod that needs software vertex processing is turbulent, so
11541 // check for it here and apply the changes if needed
11542 // and we only support that as the first one
11543 // (handling a mixture of turbulent and other tcmods would be problematic
11544 // without punting it entirely to a software path)
11545 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11547 amplitude = rsurface.texture->tcmods[0].parms[1];
11548 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
11549 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11550 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11551 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11552 for (j = 0;j < batchnumvertices;j++)
11554 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);
11555 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
11559 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11561 // convert the modified arrays to vertex structs
11562 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
11563 // rsurface.batchvertexmeshbuffer = NULL;
11564 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
11565 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11566 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
11567 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
11568 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11569 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
11570 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
11572 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11574 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
11575 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
11578 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
11579 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11580 Vector4Scale(rsurface.batchlightmapcolor4f + 4*j, 255.0f, vertexmesh->color4ub);
11581 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
11582 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11583 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
11584 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
11585 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11586 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
11590 void RSurf_DrawBatch(void)
11592 // sometimes a zero triangle surface (usually a degenerate patch) makes it
11593 // through the pipeline, killing it earlier in the pipeline would have
11594 // per-surface overhead rather than per-batch overhead, so it's best to
11595 // reject it here, before it hits glDraw.
11596 if (rsurface.batchnumtriangles == 0)
11599 // batch debugging code
11600 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
11606 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
11607 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
11610 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
11612 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
11614 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
11615 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);
11622 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);
11625 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
11627 // pick the closest matching water plane
11628 int planeindex, vertexindex, bestplaneindex = -1;
11632 r_waterstate_waterplane_t *p;
11633 qboolean prepared = false;
11635 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
11637 if(p->camera_entity != rsurface.texture->camera_entity)
11642 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11644 if(rsurface.batchnumvertices == 0)
11647 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
11649 Matrix4x4_Transform(&rsurface.matrix, v, vert);
11650 d += fabs(PlaneDiff(vert, &p->plane));
11652 if (bestd > d || bestplaneindex < 0)
11655 bestplaneindex = planeindex;
11658 return bestplaneindex;
11659 // NOTE: this MAY return a totally unrelated water plane; we can ignore
11660 // this situation though, as it might be better to render single larger
11661 // batches with useless stuff (backface culled for example) than to
11662 // render multiple smaller batches
11665 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
11668 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11669 rsurface.passcolor4f_vertexbuffer = 0;
11670 rsurface.passcolor4f_bufferoffset = 0;
11671 for (i = 0;i < rsurface.batchnumvertices;i++)
11672 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
11675 static void RSurf_DrawBatch_GL11_ApplyFog(void)
11682 if (rsurface.passcolor4f)
11684 // generate color arrays
11685 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
11686 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11687 rsurface.passcolor4f_vertexbuffer = 0;
11688 rsurface.passcolor4f_bufferoffset = 0;
11689 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)
11691 f = RSurf_FogVertex(v);
11700 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11701 rsurface.passcolor4f_vertexbuffer = 0;
11702 rsurface.passcolor4f_bufferoffset = 0;
11703 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
11705 f = RSurf_FogVertex(v);
11714 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
11721 if (!rsurface.passcolor4f)
11723 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
11724 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11725 rsurface.passcolor4f_vertexbuffer = 0;
11726 rsurface.passcolor4f_bufferoffset = 0;
11727 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)
11729 f = RSurf_FogVertex(v);
11730 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
11731 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
11732 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
11737 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
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, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
11757 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
11762 if (!rsurface.passcolor4f)
11764 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
11765 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11766 rsurface.passcolor4f_vertexbuffer = 0;
11767 rsurface.passcolor4f_bufferoffset = 0;
11768 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
11770 c2[0] = c[0] + r_refdef.scene.ambient;
11771 c2[1] = c[1] + r_refdef.scene.ambient;
11772 c2[2] = c[2] + r_refdef.scene.ambient;
11777 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11780 rsurface.passcolor4f = NULL;
11781 rsurface.passcolor4f_vertexbuffer = 0;
11782 rsurface.passcolor4f_bufferoffset = 0;
11783 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
11784 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11785 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11786 GL_Color(r, g, b, a);
11787 R_Mesh_TexBind(0, rsurface.lightmaptexture);
11791 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11793 // TODO: optimize applyfog && applycolor case
11794 // just apply fog if necessary, and tint the fog color array if necessary
11795 rsurface.passcolor4f = NULL;
11796 rsurface.passcolor4f_vertexbuffer = 0;
11797 rsurface.passcolor4f_bufferoffset = 0;
11798 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
11799 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11800 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11801 GL_Color(r, g, b, a);
11805 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11808 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
11809 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
11810 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
11811 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
11812 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11813 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11814 GL_Color(r, g, b, a);
11818 static void RSurf_DrawBatch_GL11_ClampColor(void)
11823 if (!rsurface.passcolor4f)
11825 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
11827 c2[0] = bound(0.0f, c1[0], 1.0f);
11828 c2[1] = bound(0.0f, c1[1], 1.0f);
11829 c2[2] = bound(0.0f, c1[2], 1.0f);
11830 c2[3] = bound(0.0f, c1[3], 1.0f);
11834 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
11844 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11845 rsurface.passcolor4f_vertexbuffer = 0;
11846 rsurface.passcolor4f_bufferoffset = 0;
11847 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)
11849 f = -DotProduct(r_refdef.view.forward, n);
11851 f = f * 0.85 + 0.15; // work around so stuff won't get black
11852 f *= r_refdef.lightmapintensity;
11853 Vector4Set(c, f, f, f, 1);
11857 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11859 RSurf_DrawBatch_GL11_ApplyFakeLight();
11860 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
11861 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11862 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11863 GL_Color(r, g, b, a);
11867 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
11875 vec3_t ambientcolor;
11876 vec3_t diffusecolor;
11880 VectorCopy(rsurface.modellight_lightdir, lightdir);
11881 f = 0.5f * r_refdef.lightmapintensity;
11882 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
11883 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
11884 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
11885 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
11886 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
11887 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
11889 if (VectorLength2(diffusecolor) > 0)
11891 // q3-style directional shading
11892 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11893 rsurface.passcolor4f_vertexbuffer = 0;
11894 rsurface.passcolor4f_bufferoffset = 0;
11895 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)
11897 if ((f = DotProduct(n, lightdir)) > 0)
11898 VectorMA(ambientcolor, f, diffusecolor, c);
11900 VectorCopy(ambientcolor, c);
11907 *applycolor = false;
11911 *r = ambientcolor[0];
11912 *g = ambientcolor[1];
11913 *b = ambientcolor[2];
11914 rsurface.passcolor4f = NULL;
11915 rsurface.passcolor4f_vertexbuffer = 0;
11916 rsurface.passcolor4f_bufferoffset = 0;
11920 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11922 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
11923 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
11924 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11925 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11926 GL_Color(r, g, b, a);
11930 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
11936 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
11938 f = 1 - RSurf_FogVertex(v);
11946 void RSurf_SetupDepthAndCulling(void)
11948 // submodels are biased to avoid z-fighting with world surfaces that they
11949 // may be exactly overlapping (avoids z-fighting artifacts on certain
11950 // doors and things in Quake maps)
11951 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
11952 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
11953 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
11954 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11957 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11959 // transparent sky would be ridiculous
11960 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11962 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11963 skyrenderlater = true;
11964 RSurf_SetupDepthAndCulling();
11965 GL_DepthMask(true);
11966 // LordHavoc: HalfLife maps have freaky skypolys so don't use
11967 // skymasking on them, and Quake3 never did sky masking (unlike
11968 // software Quake and software Quake2), so disable the sky masking
11969 // in Quake3 maps as it causes problems with q3map2 sky tricks,
11970 // and skymasking also looks very bad when noclipping outside the
11971 // level, so don't use it then either.
11972 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
11974 R_Mesh_ResetTextureState();
11975 if (skyrendermasked)
11977 R_SetupShader_DepthOrShadow();
11978 // depth-only (masking)
11979 GL_ColorMask(0,0,0,0);
11980 // just to make sure that braindead drivers don't draw
11981 // anything despite that colormask...
11982 GL_BlendFunc(GL_ZERO, GL_ONE);
11983 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11984 if (rsurface.batchvertex3fbuffer)
11985 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
11987 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
11991 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11993 GL_BlendFunc(GL_ONE, GL_ZERO);
11994 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11995 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
11996 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11999 if (skyrendermasked)
12000 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12002 R_Mesh_ResetTextureState();
12003 GL_Color(1, 1, 1, 1);
12006 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
12007 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
12008 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12010 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
12014 // render screenspace normalmap to texture
12015 GL_DepthMask(true);
12016 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
12021 // bind lightmap texture
12023 // water/refraction/reflection/camera surfaces have to be handled specially
12024 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
12026 int start, end, startplaneindex;
12027 for (start = 0;start < texturenumsurfaces;start = end)
12029 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
12030 if(startplaneindex < 0)
12032 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
12033 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
12037 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
12039 // now that we have a batch using the same planeindex, render it
12040 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
12042 // render water or distortion background
12043 GL_DepthMask(true);
12044 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));
12046 // blend surface on top
12047 GL_DepthMask(false);
12048 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
12051 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
12053 // render surface with reflection texture as input
12054 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12055 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));
12062 // render surface batch normally
12063 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12064 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
12068 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12070 // OpenGL 1.3 path - anything not completely ancient
12071 qboolean applycolor;
12074 const texturelayer_t *layer;
12075 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);
12076 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12078 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12081 int layertexrgbscale;
12082 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12084 if (layerindex == 0)
12085 GL_AlphaTest(true);
12088 GL_AlphaTest(false);
12089 GL_DepthFunc(GL_EQUAL);
12092 GL_DepthMask(layer->depthmask && writedepth);
12093 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12094 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
12096 layertexrgbscale = 4;
12097 VectorScale(layer->color, 0.25f, layercolor);
12099 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
12101 layertexrgbscale = 2;
12102 VectorScale(layer->color, 0.5f, layercolor);
12106 layertexrgbscale = 1;
12107 VectorScale(layer->color, 1.0f, layercolor);
12109 layercolor[3] = layer->color[3];
12110 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
12111 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12112 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12113 switch (layer->type)
12115 case TEXTURELAYERTYPE_LITTEXTURE:
12116 // single-pass lightmapped texture with 2x rgbscale
12117 R_Mesh_TexBind(0, r_texture_white);
12118 R_Mesh_TexMatrix(0, NULL);
12119 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12120 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12121 R_Mesh_TexBind(1, layer->texture);
12122 R_Mesh_TexMatrix(1, &layer->texmatrix);
12123 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12124 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12125 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12126 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12127 else if (FAKELIGHT_ENABLED)
12128 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12129 else if (rsurface.uselightmaptexture)
12130 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12132 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12134 case TEXTURELAYERTYPE_TEXTURE:
12135 // singletexture unlit texture with transparency support
12136 R_Mesh_TexBind(0, layer->texture);
12137 R_Mesh_TexMatrix(0, &layer->texmatrix);
12138 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12139 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12140 R_Mesh_TexBind(1, 0);
12141 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12142 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12144 case TEXTURELAYERTYPE_FOG:
12145 // singletexture fogging
12146 if (layer->texture)
12148 R_Mesh_TexBind(0, layer->texture);
12149 R_Mesh_TexMatrix(0, &layer->texmatrix);
12150 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12151 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12155 R_Mesh_TexBind(0, 0);
12156 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12158 R_Mesh_TexBind(1, 0);
12159 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12160 // generate a color array for the fog pass
12161 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
12162 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
12166 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12169 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12171 GL_DepthFunc(GL_LEQUAL);
12172 GL_AlphaTest(false);
12176 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12178 // OpenGL 1.1 - crusty old voodoo path
12181 const texturelayer_t *layer;
12182 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);
12183 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12185 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12187 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12189 if (layerindex == 0)
12190 GL_AlphaTest(true);
12193 GL_AlphaTest(false);
12194 GL_DepthFunc(GL_EQUAL);
12197 GL_DepthMask(layer->depthmask && writedepth);
12198 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12199 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12200 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12201 switch (layer->type)
12203 case TEXTURELAYERTYPE_LITTEXTURE:
12204 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
12206 // two-pass lit texture with 2x rgbscale
12207 // first the lightmap pass
12208 R_Mesh_TexBind(0, r_texture_white);
12209 R_Mesh_TexMatrix(0, NULL);
12210 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12211 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12212 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12213 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
12214 else if (FAKELIGHT_ENABLED)
12215 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
12216 else if (rsurface.uselightmaptexture)
12217 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
12219 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
12220 // then apply the texture to it
12221 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
12222 R_Mesh_TexBind(0, layer->texture);
12223 R_Mesh_TexMatrix(0, &layer->texmatrix);
12224 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12225 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12226 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);
12230 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
12231 R_Mesh_TexBind(0, layer->texture);
12232 R_Mesh_TexMatrix(0, &layer->texmatrix);
12233 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12234 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12235 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12236 RSurf_DrawBatch_GL11_VertexShade(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);
12238 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);
12241 case TEXTURELAYERTYPE_TEXTURE:
12242 // singletexture unlit texture with transparency support
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], 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);
12249 case TEXTURELAYERTYPE_FOG:
12250 // singletexture fogging
12251 if (layer->texture)
12253 R_Mesh_TexBind(0, layer->texture);
12254 R_Mesh_TexMatrix(0, &layer->texmatrix);
12255 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12256 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12260 R_Mesh_TexBind(0, 0);
12261 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12263 // generate a color array for the fog pass
12264 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
12265 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
12269 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12272 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12274 GL_DepthFunc(GL_LEQUAL);
12275 GL_AlphaTest(false);
12279 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12283 r_vertexgeneric_t *batchvertex;
12286 // R_Mesh_ResetTextureState();
12287 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12289 if(rsurface.texture && rsurface.texture->currentskinframe)
12291 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
12292 c[3] *= rsurface.texture->currentalpha;
12302 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
12304 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
12305 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
12306 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
12309 // brighten it up (as texture value 127 means "unlit")
12310 c[0] *= 2 * r_refdef.view.colorscale;
12311 c[1] *= 2 * r_refdef.view.colorscale;
12312 c[2] *= 2 * r_refdef.view.colorscale;
12314 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
12315 c[3] *= r_wateralpha.value;
12317 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
12319 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12320 GL_DepthMask(false);
12322 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
12324 GL_BlendFunc(GL_ONE, GL_ONE);
12325 GL_DepthMask(false);
12327 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12329 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
12330 GL_DepthMask(false);
12332 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
12334 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
12335 GL_DepthMask(false);
12339 GL_BlendFunc(GL_ONE, GL_ZERO);
12340 GL_DepthMask(writedepth);
12343 if (r_showsurfaces.integer == 3)
12345 rsurface.passcolor4f = NULL;
12347 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
12349 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12351 rsurface.passcolor4f = NULL;
12352 rsurface.passcolor4f_vertexbuffer = 0;
12353 rsurface.passcolor4f_bufferoffset = 0;
12355 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12357 qboolean applycolor = true;
12360 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12362 r_refdef.lightmapintensity = 1;
12363 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
12364 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12366 else if (FAKELIGHT_ENABLED)
12368 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12370 r_refdef.lightmapintensity = r_fakelight_intensity.value;
12371 RSurf_DrawBatch_GL11_ApplyFakeLight();
12372 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12376 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12378 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12379 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12380 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12383 if(!rsurface.passcolor4f)
12384 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
12386 RSurf_DrawBatch_GL11_ApplyAmbient();
12387 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
12388 if(r_refdef.fogenabled)
12389 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
12390 RSurf_DrawBatch_GL11_ClampColor();
12392 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
12393 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12396 else if (!r_refdef.view.showdebug)
12398 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12399 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12400 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12402 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12403 Vector4Set(batchvertex[vi].color4ub, 0, 0, 0, 255);
12405 R_Mesh_PrepareVertices_Generic_Unlock();
12408 else if (r_showsurfaces.integer == 4)
12410 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12411 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12412 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12414 unsigned char c = vi << 3;
12415 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12416 Vector4Set(batchvertex[vi].color4ub, c, c, c, 255);
12418 R_Mesh_PrepareVertices_Generic_Unlock();
12421 else if (r_showsurfaces.integer == 2)
12424 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12425 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
12426 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
12428 unsigned char c = (j + rsurface.batchfirsttriangle) << 3;
12429 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
12430 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
12431 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
12432 Vector4Set(batchvertex[j*3+0].color4ub, c, c, c, 255);
12433 Vector4Set(batchvertex[j*3+1].color4ub, c, c, c, 255);
12434 Vector4Set(batchvertex[j*3+2].color4ub, c, c, c, 255);
12436 R_Mesh_PrepareVertices_Generic_Unlock();
12437 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
12441 int texturesurfaceindex;
12443 const msurface_t *surface;
12444 unsigned char surfacecolor4ub[4];
12445 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12446 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
12448 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
12450 surface = texturesurfacelist[texturesurfaceindex];
12451 k = (int)(((size_t)surface) / sizeof(msurface_t));
12452 Vector4Set(surfacecolor4ub, (k & 0xF) << 4, (k & 0xF0), (k & 0xF00) >> 4, 255);
12453 for (j = 0;j < surface->num_vertices;j++)
12455 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12456 Vector4Copy(surfacecolor4ub, batchvertex[vi].color4ub);
12460 R_Mesh_PrepareVertices_Generic_Unlock();
12465 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12468 RSurf_SetupDepthAndCulling();
12469 if (r_showsurfaces.integer)
12471 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12474 switch (vid.renderpath)
12476 case RENDERPATH_GL20:
12477 case RENDERPATH_D3D9:
12478 case RENDERPATH_D3D10:
12479 case RENDERPATH_D3D11:
12480 case RENDERPATH_SOFT:
12481 case RENDERPATH_GLES2:
12482 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12484 case RENDERPATH_GL13:
12485 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
12487 case RENDERPATH_GL11:
12488 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
12494 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12497 RSurf_SetupDepthAndCulling();
12498 if (r_showsurfaces.integer)
12500 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12503 switch (vid.renderpath)
12505 case RENDERPATH_GL20:
12506 case RENDERPATH_D3D9:
12507 case RENDERPATH_D3D10:
12508 case RENDERPATH_D3D11:
12509 case RENDERPATH_SOFT:
12510 case RENDERPATH_GLES2:
12511 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12513 case RENDERPATH_GL13:
12514 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
12516 case RENDERPATH_GL11:
12517 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
12523 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
12526 int texturenumsurfaces, endsurface;
12527 texture_t *texture;
12528 const msurface_t *surface;
12529 #define MAXBATCH_TRANSPARENTSURFACES 256
12530 const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
12532 // if the model is static it doesn't matter what value we give for
12533 // wantnormals and wanttangents, so this logic uses only rules applicable
12534 // to a model, knowing that they are meaningless otherwise
12535 if (ent == r_refdef.scene.worldentity)
12536 RSurf_ActiveWorldEntity();
12537 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12538 RSurf_ActiveModelEntity(ent, false, false, false);
12541 switch (vid.renderpath)
12543 case RENDERPATH_GL20:
12544 case RENDERPATH_D3D9:
12545 case RENDERPATH_D3D10:
12546 case RENDERPATH_D3D11:
12547 case RENDERPATH_SOFT:
12548 case RENDERPATH_GLES2:
12549 RSurf_ActiveModelEntity(ent, true, true, false);
12551 case RENDERPATH_GL13:
12552 case RENDERPATH_GL11:
12553 RSurf_ActiveModelEntity(ent, true, false, false);
12558 if (r_transparentdepthmasking.integer)
12560 qboolean setup = false;
12561 for (i = 0;i < numsurfaces;i = j)
12564 surface = rsurface.modelsurfaces + surfacelist[i];
12565 texture = surface->texture;
12566 rsurface.texture = R_GetCurrentTexture(texture);
12567 rsurface.lightmaptexture = NULL;
12568 rsurface.deluxemaptexture = NULL;
12569 rsurface.uselightmaptexture = false;
12570 // scan ahead until we find a different texture
12571 endsurface = min(i + 1024, numsurfaces);
12572 texturenumsurfaces = 0;
12573 texturesurfacelist[texturenumsurfaces++] = surface;
12574 for (;j < endsurface;j++)
12576 surface = rsurface.modelsurfaces + surfacelist[j];
12577 if (texture != surface->texture)
12579 texturesurfacelist[texturenumsurfaces++] = surface;
12581 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
12583 // render the range of surfaces as depth
12587 GL_ColorMask(0,0,0,0);
12589 GL_DepthTest(true);
12590 GL_BlendFunc(GL_ONE, GL_ZERO);
12591 GL_DepthMask(true);
12592 // R_Mesh_ResetTextureState();
12593 R_SetupShader_DepthOrShadow();
12595 RSurf_SetupDepthAndCulling();
12596 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
12597 if (rsurface.batchvertex3fbuffer)
12598 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
12600 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
12604 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12607 for (i = 0;i < numsurfaces;i = j)
12610 surface = rsurface.modelsurfaces + surfacelist[i];
12611 texture = surface->texture;
12612 rsurface.texture = R_GetCurrentTexture(texture);
12613 // scan ahead until we find a different texture
12614 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
12615 texturenumsurfaces = 0;
12616 texturesurfacelist[texturenumsurfaces++] = surface;
12617 if(FAKELIGHT_ENABLED)
12619 rsurface.lightmaptexture = NULL;
12620 rsurface.deluxemaptexture = NULL;
12621 rsurface.uselightmaptexture = false;
12622 for (;j < endsurface;j++)
12624 surface = rsurface.modelsurfaces + surfacelist[j];
12625 if (texture != surface->texture)
12627 texturesurfacelist[texturenumsurfaces++] = surface;
12632 rsurface.lightmaptexture = surface->lightmaptexture;
12633 rsurface.deluxemaptexture = surface->deluxemaptexture;
12634 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
12635 for (;j < endsurface;j++)
12637 surface = rsurface.modelsurfaces + surfacelist[j];
12638 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
12640 texturesurfacelist[texturenumsurfaces++] = surface;
12643 // render the range of surfaces
12644 if (ent == r_refdef.scene.worldentity)
12645 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
12647 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
12649 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12652 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
12654 // transparent surfaces get pushed off into the transparent queue
12655 int surfacelistindex;
12656 const msurface_t *surface;
12657 vec3_t tempcenter, center;
12658 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
12660 surface = texturesurfacelist[surfacelistindex];
12661 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
12662 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
12663 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
12664 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
12665 if (queueentity->transparent_offset) // transparent offset
12667 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
12668 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
12669 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
12671 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
12675 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12677 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
12679 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
12681 RSurf_SetupDepthAndCulling();
12682 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
12683 if (rsurface.batchvertex3fbuffer)
12684 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
12686 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
12690 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
12692 const entity_render_t *queueentity = r_refdef.scene.worldentity;
12695 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
12698 if (!rsurface.texture->currentnumlayers)
12700 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12701 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12703 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12705 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
12706 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
12707 else if (!rsurface.texture->currentnumlayers)
12709 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
12711 // in the deferred case, transparent surfaces were queued during prepass
12712 if (!r_shadow_usingdeferredprepass)
12713 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12717 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
12718 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
12723 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
12726 texture_t *texture;
12727 R_FrameData_SetMark();
12728 // break the surface list down into batches by texture and use of lightmapping
12729 for (i = 0;i < numsurfaces;i = j)
12732 // texture is the base texture pointer, rsurface.texture is the
12733 // current frame/skin the texture is directing us to use (for example
12734 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
12735 // use skin 1 instead)
12736 texture = surfacelist[i]->texture;
12737 rsurface.texture = R_GetCurrentTexture(texture);
12738 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
12740 // if this texture is not the kind we want, skip ahead to the next one
12741 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12745 if(FAKELIGHT_ENABLED || depthonly || prepass)
12747 rsurface.lightmaptexture = NULL;
12748 rsurface.deluxemaptexture = NULL;
12749 rsurface.uselightmaptexture = false;
12750 // simply scan ahead until we find a different texture or lightmap state
12751 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12756 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
12757 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
12758 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
12759 // simply scan ahead until we find a different texture or lightmap state
12760 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
12763 // render the range of surfaces
12764 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
12766 R_FrameData_ReturnToMark();
12769 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
12773 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
12776 if (!rsurface.texture->currentnumlayers)
12778 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12779 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12781 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12783 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
12784 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
12785 else if (!rsurface.texture->currentnumlayers)
12787 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
12789 // in the deferred case, transparent surfaces were queued during prepass
12790 if (!r_shadow_usingdeferredprepass)
12791 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12795 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
12796 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
12801 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
12804 texture_t *texture;
12805 R_FrameData_SetMark();
12806 // break the surface list down into batches by texture and use of lightmapping
12807 for (i = 0;i < numsurfaces;i = j)
12810 // texture is the base texture pointer, rsurface.texture is the
12811 // current frame/skin the texture is directing us to use (for example
12812 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
12813 // use skin 1 instead)
12814 texture = surfacelist[i]->texture;
12815 rsurface.texture = R_GetCurrentTexture(texture);
12816 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
12818 // if this texture is not the kind we want, skip ahead to the next one
12819 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12823 if(FAKELIGHT_ENABLED || depthonly || prepass)
12825 rsurface.lightmaptexture = NULL;
12826 rsurface.deluxemaptexture = NULL;
12827 rsurface.uselightmaptexture = false;
12828 // simply scan ahead until we find a different texture or lightmap state
12829 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12834 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
12835 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
12836 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
12837 // simply scan ahead until we find a different texture or lightmap state
12838 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
12841 // render the range of surfaces
12842 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
12844 R_FrameData_ReturnToMark();
12847 float locboxvertex3f[6*4*3] =
12849 1,0,1, 1,0,0, 1,1,0, 1,1,1,
12850 0,1,1, 0,1,0, 0,0,0, 0,0,1,
12851 1,1,1, 1,1,0, 0,1,0, 0,1,1,
12852 0,0,1, 0,0,0, 1,0,0, 1,0,1,
12853 0,0,1, 1,0,1, 1,1,1, 0,1,1,
12854 1,0,0, 0,0,0, 0,1,0, 1,1,0
12857 unsigned short locboxelements[6*2*3] =
12862 12,13,14, 12,14,15,
12863 16,17,18, 16,18,19,
12867 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
12870 cl_locnode_t *loc = (cl_locnode_t *)ent;
12872 float vertex3f[6*4*3];
12874 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12875 GL_DepthMask(false);
12876 GL_DepthRange(0, 1);
12877 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12878 GL_DepthTest(true);
12879 GL_CullFace(GL_NONE);
12880 R_EntityMatrix(&identitymatrix);
12882 // R_Mesh_ResetTextureState();
12884 i = surfacelist[0];
12885 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12886 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12887 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12888 surfacelist[0] < 0 ? 0.5f : 0.125f);
12890 if (VectorCompare(loc->mins, loc->maxs))
12892 VectorSet(size, 2, 2, 2);
12893 VectorMA(loc->mins, -0.5f, size, mins);
12897 VectorCopy(loc->mins, mins);
12898 VectorSubtract(loc->maxs, loc->mins, size);
12901 for (i = 0;i < 6*4*3;)
12902 for (j = 0;j < 3;j++, i++)
12903 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
12905 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
12906 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12907 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
12910 void R_DrawLocs(void)
12913 cl_locnode_t *loc, *nearestloc;
12915 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
12916 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
12918 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
12919 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
12923 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
12925 if (decalsystem->decals)
12926 Mem_Free(decalsystem->decals);
12927 memset(decalsystem, 0, sizeof(*decalsystem));
12930 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)
12933 tridecal_t *decals;
12936 // expand or initialize the system
12937 if (decalsystem->maxdecals <= decalsystem->numdecals)
12939 decalsystem_t old = *decalsystem;
12940 qboolean useshortelements;
12941 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
12942 useshortelements = decalsystem->maxdecals * 3 <= 65536;
12943 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)));
12944 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
12945 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
12946 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
12947 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
12948 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
12949 if (decalsystem->numdecals)
12950 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
12952 Mem_Free(old.decals);
12953 for (i = 0;i < decalsystem->maxdecals*3;i++)
12954 decalsystem->element3i[i] = i;
12955 if (useshortelements)
12956 for (i = 0;i < decalsystem->maxdecals*3;i++)
12957 decalsystem->element3s[i] = i;
12960 // grab a decal and search for another free slot for the next one
12961 decals = decalsystem->decals;
12962 decal = decalsystem->decals + (i = decalsystem->freedecal++);
12963 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
12965 decalsystem->freedecal = i;
12966 if (decalsystem->numdecals <= i)
12967 decalsystem->numdecals = i + 1;
12969 // initialize the decal
12971 decal->triangleindex = triangleindex;
12972 decal->surfaceindex = surfaceindex;
12973 decal->decalsequence = decalsequence;
12974 decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
12975 decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
12976 decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
12977 decal->color4ub[0][3] = 255;
12978 decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
12979 decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
12980 decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
12981 decal->color4ub[1][3] = 255;
12982 decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
12983 decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
12984 decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
12985 decal->color4ub[2][3] = 255;
12986 decal->vertex3f[0][0] = v0[0];
12987 decal->vertex3f[0][1] = v0[1];
12988 decal->vertex3f[0][2] = v0[2];
12989 decal->vertex3f[1][0] = v1[0];
12990 decal->vertex3f[1][1] = v1[1];
12991 decal->vertex3f[1][2] = v1[2];
12992 decal->vertex3f[2][0] = v2[0];
12993 decal->vertex3f[2][1] = v2[1];
12994 decal->vertex3f[2][2] = v2[2];
12995 decal->texcoord2f[0][0] = t0[0];
12996 decal->texcoord2f[0][1] = t0[1];
12997 decal->texcoord2f[1][0] = t1[0];
12998 decal->texcoord2f[1][1] = t1[1];
12999 decal->texcoord2f[2][0] = t2[0];
13000 decal->texcoord2f[2][1] = t2[1];
13003 extern cvar_t cl_decals_bias;
13004 extern cvar_t cl_decals_models;
13005 extern cvar_t cl_decals_newsystem_intensitymultiplier;
13006 // baseparms, parms, temps
13007 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)
13012 const float *vertex3f;
13014 float points[2][9][3];
13021 e = rsurface.modelelement3i + 3*triangleindex;
13023 vertex3f = rsurface.modelvertex3f;
13025 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13027 index = 3*e[cornerindex];
13028 VectorCopy(vertex3f + index, v[cornerindex]);
13031 //TriangleNormal(v[0], v[1], v[2], normal);
13032 //if (DotProduct(normal, localnormal) < 0.0f)
13034 // clip by each of the box planes formed from the projection matrix
13035 // if anything survives, we emit the decal
13036 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]);
13039 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]);
13042 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]);
13045 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]);
13048 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]);
13051 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]);
13054 // some part of the triangle survived, so we have to accept it...
13057 // dynamic always uses the original triangle
13059 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13061 index = 3*e[cornerindex];
13062 VectorCopy(vertex3f + index, v[cornerindex]);
13065 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
13067 // convert vertex positions to texcoords
13068 Matrix4x4_Transform(projection, v[cornerindex], temp);
13069 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
13070 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
13071 // calculate distance fade from the projection origin
13072 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
13073 f = bound(0.0f, f, 1.0f);
13074 c[cornerindex][0] = r * f;
13075 c[cornerindex][1] = g * f;
13076 c[cornerindex][2] = b * f;
13077 c[cornerindex][3] = 1.0f;
13078 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
13081 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);
13083 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
13084 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);
13086 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)
13088 matrix4x4_t projection;
13089 decalsystem_t *decalsystem;
13092 const msurface_t *surface;
13093 const msurface_t *surfaces;
13094 const int *surfacelist;
13095 const texture_t *texture;
13097 int numsurfacelist;
13098 int surfacelistindex;
13101 float localorigin[3];
13102 float localnormal[3];
13103 float localmins[3];
13104 float localmaxs[3];
13107 float planes[6][4];
13110 int bih_triangles_count;
13111 int bih_triangles[256];
13112 int bih_surfaces[256];
13114 decalsystem = &ent->decalsystem;
13115 model = ent->model;
13116 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
13118 R_DecalSystem_Reset(&ent->decalsystem);
13122 if (!model->brush.data_leafs && !cl_decals_models.integer)
13124 if (decalsystem->model)
13125 R_DecalSystem_Reset(decalsystem);
13129 if (decalsystem->model != model)
13130 R_DecalSystem_Reset(decalsystem);
13131 decalsystem->model = model;
13133 RSurf_ActiveModelEntity(ent, false, false, false);
13135 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
13136 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
13137 VectorNormalize(localnormal);
13138 localsize = worldsize*rsurface.inversematrixscale;
13139 localmins[0] = localorigin[0] - localsize;
13140 localmins[1] = localorigin[1] - localsize;
13141 localmins[2] = localorigin[2] - localsize;
13142 localmaxs[0] = localorigin[0] + localsize;
13143 localmaxs[1] = localorigin[1] + localsize;
13144 localmaxs[2] = localorigin[2] + localsize;
13146 //VectorCopy(localnormal, planes[4]);
13147 //VectorVectors(planes[4], planes[2], planes[0]);
13148 AnglesFromVectors(angles, localnormal, NULL, false);
13149 AngleVectors(angles, planes[0], planes[2], planes[4]);
13150 VectorNegate(planes[0], planes[1]);
13151 VectorNegate(planes[2], planes[3]);
13152 VectorNegate(planes[4], planes[5]);
13153 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
13154 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
13155 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
13156 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
13157 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
13158 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
13163 matrix4x4_t forwardprojection;
13164 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
13165 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
13170 float projectionvector[4][3];
13171 VectorScale(planes[0], ilocalsize, projectionvector[0]);
13172 VectorScale(planes[2], ilocalsize, projectionvector[1]);
13173 VectorScale(planes[4], ilocalsize, projectionvector[2]);
13174 projectionvector[0][0] = planes[0][0] * ilocalsize;
13175 projectionvector[0][1] = planes[1][0] * ilocalsize;
13176 projectionvector[0][2] = planes[2][0] * ilocalsize;
13177 projectionvector[1][0] = planes[0][1] * ilocalsize;
13178 projectionvector[1][1] = planes[1][1] * ilocalsize;
13179 projectionvector[1][2] = planes[2][1] * ilocalsize;
13180 projectionvector[2][0] = planes[0][2] * ilocalsize;
13181 projectionvector[2][1] = planes[1][2] * ilocalsize;
13182 projectionvector[2][2] = planes[2][2] * ilocalsize;
13183 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
13184 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
13185 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
13186 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
13190 dynamic = model->surfmesh.isanimated;
13191 numsurfacelist = model->nummodelsurfaces;
13192 surfacelist = model->sortedmodelsurfaces;
13193 surfaces = model->data_surfaces;
13196 bih_triangles_count = -1;
13199 if(model->render_bih.numleafs)
13200 bih = &model->render_bih;
13201 else if(model->collision_bih.numleafs)
13202 bih = &model->collision_bih;
13205 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
13206 if(bih_triangles_count == 0)
13208 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
13210 if(bih_triangles_count > 0)
13212 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
13214 surfaceindex = bih_surfaces[triangleindex];
13215 surface = surfaces + surfaceindex;
13216 texture = surface->texture;
13217 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13219 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13221 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
13226 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
13228 surfaceindex = surfacelist[surfacelistindex];
13229 surface = surfaces + surfaceindex;
13230 // check cull box first because it rejects more than any other check
13231 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
13233 // skip transparent surfaces
13234 texture = surface->texture;
13235 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13237 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13239 numtriangles = surface->num_triangles;
13240 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
13241 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
13246 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
13247 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)
13249 int renderentityindex;
13250 float worldmins[3];
13251 float worldmaxs[3];
13252 entity_render_t *ent;
13254 if (!cl_decals_newsystem.integer)
13257 worldmins[0] = worldorigin[0] - worldsize;
13258 worldmins[1] = worldorigin[1] - worldsize;
13259 worldmins[2] = worldorigin[2] - worldsize;
13260 worldmaxs[0] = worldorigin[0] + worldsize;
13261 worldmaxs[1] = worldorigin[1] + worldsize;
13262 worldmaxs[2] = worldorigin[2] + worldsize;
13264 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13266 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
13268 ent = r_refdef.scene.entities[renderentityindex];
13269 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
13272 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13276 typedef struct r_decalsystem_splatqueue_s
13278 vec3_t worldorigin;
13279 vec3_t worldnormal;
13285 r_decalsystem_splatqueue_t;
13287 int r_decalsystem_numqueued = 0;
13288 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
13290 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)
13292 r_decalsystem_splatqueue_t *queue;
13294 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
13297 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
13298 VectorCopy(worldorigin, queue->worldorigin);
13299 VectorCopy(worldnormal, queue->worldnormal);
13300 Vector4Set(queue->color, r, g, b, a);
13301 Vector4Set(queue->tcrange, s1, t1, s2, t2);
13302 queue->worldsize = worldsize;
13303 queue->decalsequence = cl.decalsequence++;
13306 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
13309 r_decalsystem_splatqueue_t *queue;
13311 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
13312 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);
13313 r_decalsystem_numqueued = 0;
13316 extern cvar_t cl_decals_max;
13317 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
13320 decalsystem_t *decalsystem = &ent->decalsystem;
13327 if (!decalsystem->numdecals)
13330 if (r_showsurfaces.integer)
13333 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13335 R_DecalSystem_Reset(decalsystem);
13339 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
13340 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
13342 if (decalsystem->lastupdatetime)
13343 frametime = (cl.time - decalsystem->lastupdatetime);
13346 decalsystem->lastupdatetime = cl.time;
13347 decal = decalsystem->decals;
13348 numdecals = decalsystem->numdecals;
13350 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13352 if (decal->color4ub[0][3])
13354 decal->lived += frametime;
13355 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
13357 memset(decal, 0, sizeof(*decal));
13358 if (decalsystem->freedecal > i)
13359 decalsystem->freedecal = i;
13363 decal = decalsystem->decals;
13364 while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
13367 // collapse the array by shuffling the tail decals into the gaps
13370 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
13371 decalsystem->freedecal++;
13372 if (decalsystem->freedecal == numdecals)
13374 decal[decalsystem->freedecal] = decal[--numdecals];
13377 decalsystem->numdecals = numdecals;
13379 if (numdecals <= 0)
13381 // if there are no decals left, reset decalsystem
13382 R_DecalSystem_Reset(decalsystem);
13386 extern skinframe_t *decalskinframe;
13387 static void R_DrawModelDecals_Entity(entity_render_t *ent)
13390 decalsystem_t *decalsystem = &ent->decalsystem;
13399 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
13402 numdecals = decalsystem->numdecals;
13406 if (r_showsurfaces.integer)
13409 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13411 R_DecalSystem_Reset(decalsystem);
13415 // if the model is static it doesn't matter what value we give for
13416 // wantnormals and wanttangents, so this logic uses only rules applicable
13417 // to a model, knowing that they are meaningless otherwise
13418 if (ent == r_refdef.scene.worldentity)
13419 RSurf_ActiveWorldEntity();
13421 RSurf_ActiveModelEntity(ent, false, false, false);
13423 decalsystem->lastupdatetime = cl.time;
13424 decal = decalsystem->decals;
13426 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
13428 // update vertex positions for animated models
13429 v3f = decalsystem->vertex3f;
13430 c4f = decalsystem->color4f;
13431 t2f = decalsystem->texcoord2f;
13432 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13434 if (!decal->color4ub[0][3])
13437 if (surfacevisible && !surfacevisible[decal->surfaceindex])
13440 // update color values for fading decals
13441 if (decal->lived >= cl_decals_time.value)
13443 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
13444 alpha *= (1.0f/255.0f);
13447 alpha = 1.0f/255.0f;
13449 c4f[ 0] = decal->color4ub[0][0] * alpha;
13450 c4f[ 1] = decal->color4ub[0][1] * alpha;
13451 c4f[ 2] = decal->color4ub[0][2] * alpha;
13453 c4f[ 4] = decal->color4ub[1][0] * alpha;
13454 c4f[ 5] = decal->color4ub[1][1] * alpha;
13455 c4f[ 6] = decal->color4ub[1][2] * alpha;
13457 c4f[ 8] = decal->color4ub[2][0] * alpha;
13458 c4f[ 9] = decal->color4ub[2][1] * alpha;
13459 c4f[10] = decal->color4ub[2][2] * alpha;
13462 t2f[0] = decal->texcoord2f[0][0];
13463 t2f[1] = decal->texcoord2f[0][1];
13464 t2f[2] = decal->texcoord2f[1][0];
13465 t2f[3] = decal->texcoord2f[1][1];
13466 t2f[4] = decal->texcoord2f[2][0];
13467 t2f[5] = decal->texcoord2f[2][1];
13469 // update vertex positions for animated models
13470 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
13472 e = rsurface.modelelement3i + 3*decal->triangleindex;
13473 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
13474 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
13475 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
13479 VectorCopy(decal->vertex3f[0], v3f);
13480 VectorCopy(decal->vertex3f[1], v3f + 3);
13481 VectorCopy(decal->vertex3f[2], v3f + 6);
13484 if (r_refdef.fogenabled)
13486 alpha = RSurf_FogVertex(v3f);
13487 VectorScale(c4f, alpha, c4f);
13488 alpha = RSurf_FogVertex(v3f + 3);
13489 VectorScale(c4f + 4, alpha, c4f + 4);
13490 alpha = RSurf_FogVertex(v3f + 6);
13491 VectorScale(c4f + 8, alpha, c4f + 8);
13502 r_refdef.stats.drawndecals += numtris;
13504 // now render the decals all at once
13505 // (this assumes they all use one particle font texture!)
13506 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);
13507 // R_Mesh_ResetTextureState();
13508 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
13509 GL_DepthMask(false);
13510 GL_DepthRange(0, 1);
13511 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
13512 GL_DepthTest(true);
13513 GL_CullFace(GL_NONE);
13514 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
13515 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
13516 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
13520 static void R_DrawModelDecals(void)
13524 // fade faster when there are too many decals
13525 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
13526 for (i = 0;i < r_refdef.scene.numentities;i++)
13527 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
13529 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
13530 for (i = 0;i < r_refdef.scene.numentities;i++)
13531 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
13532 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
13534 R_DecalSystem_ApplySplatEntitiesQueue();
13536 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
13537 for (i = 0;i < r_refdef.scene.numentities;i++)
13538 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
13540 r_refdef.stats.totaldecals += numdecals;
13542 if (r_showsurfaces.integer)
13545 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
13547 for (i = 0;i < r_refdef.scene.numentities;i++)
13549 if (!r_refdef.viewcache.entityvisible[i])
13551 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
13552 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
13556 extern cvar_t mod_collision_bih;
13557 void R_DrawDebugModel(void)
13559 entity_render_t *ent = rsurface.entity;
13560 int i, j, k, l, flagsmask;
13561 const msurface_t *surface;
13562 dp_model_t *model = ent->model;
13565 switch(vid.renderpath)
13567 case RENDERPATH_GL11:
13568 case RENDERPATH_GL13:
13569 case RENDERPATH_GL20:
13571 case RENDERPATH_D3D9:
13572 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13574 case RENDERPATH_D3D10:
13575 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13577 case RENDERPATH_D3D11:
13578 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13580 case RENDERPATH_SOFT:
13581 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13583 case RENDERPATH_GLES2:
13584 //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13588 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
13590 // R_Mesh_ResetTextureState();
13591 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13592 GL_DepthRange(0, 1);
13593 GL_DepthTest(!r_showdisabledepthtest.integer);
13594 GL_DepthMask(false);
13595 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13597 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
13601 qboolean cullbox = ent == r_refdef.scene.worldentity;
13602 const q3mbrush_t *brush;
13603 const bih_t *bih = &model->collision_bih;
13604 const bih_leaf_t *bihleaf;
13605 float vertex3f[3][3];
13606 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
13608 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
13610 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
13612 switch (bihleaf->type)
13615 brush = model->brush.data_brushes + bihleaf->itemindex;
13616 if (brush->colbrushf && brush->colbrushf->numtriangles)
13618 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);
13619 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
13620 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
13623 case BIH_COLLISIONTRIANGLE:
13624 triangleindex = bihleaf->itemindex;
13625 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
13626 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
13627 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
13628 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);
13629 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
13630 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
13632 case BIH_RENDERTRIANGLE:
13633 triangleindex = bihleaf->itemindex;
13634 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
13635 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
13636 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
13637 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);
13638 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
13639 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
13645 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13647 if (r_showtris.integer || (r_shownormals.value != 0))
13649 if (r_showdisabledepthtest.integer)
13651 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13652 GL_DepthMask(false);
13656 GL_BlendFunc(GL_ONE, GL_ZERO);
13657 GL_DepthMask(true);
13659 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
13661 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
13663 rsurface.texture = R_GetCurrentTexture(surface->texture);
13664 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
13666 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
13667 if (r_showtris.value > 0)
13669 if (!rsurface.texture->currentlayers->depthmask)
13670 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
13671 else if (ent == r_refdef.scene.worldentity)
13672 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
13674 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
13675 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
13676 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
13678 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
13681 if (r_shownormals.value < 0)
13683 qglBegin(GL_LINES);
13684 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
13686 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13687 GL_Color(0, 0, r_refdef.view.colorscale, 1);
13688 qglVertex3f(v[0], v[1], v[2]);
13689 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
13690 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
13691 qglVertex3f(v[0], v[1], v[2]);
13696 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
13698 qglBegin(GL_LINES);
13699 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
13701 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13702 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
13703 qglVertex3f(v[0], v[1], v[2]);
13704 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
13705 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
13706 qglVertex3f(v[0], v[1], v[2]);
13710 qglBegin(GL_LINES);
13711 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
13713 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13714 GL_Color(0, r_refdef.view.colorscale, 0, 1);
13715 qglVertex3f(v[0], v[1], v[2]);
13716 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
13717 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
13718 qglVertex3f(v[0], v[1], v[2]);
13722 qglBegin(GL_LINES);
13723 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
13725 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13726 GL_Color(0, 0, r_refdef.view.colorscale, 1);
13727 qglVertex3f(v[0], v[1], v[2]);
13728 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
13729 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
13730 qglVertex3f(v[0], v[1], v[2]);
13737 rsurface.texture = NULL;
13741 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
13742 int r_maxsurfacelist = 0;
13743 const msurface_t **r_surfacelist = NULL;
13744 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
13746 int i, j, endj, flagsmask;
13747 dp_model_t *model = r_refdef.scene.worldmodel;
13748 msurface_t *surfaces;
13749 unsigned char *update;
13750 int numsurfacelist = 0;
13754 if (r_maxsurfacelist < model->num_surfaces)
13756 r_maxsurfacelist = model->num_surfaces;
13758 Mem_Free((msurface_t**)r_surfacelist);
13759 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
13762 RSurf_ActiveWorldEntity();
13764 surfaces = model->data_surfaces;
13765 update = model->brushq1.lightmapupdateflags;
13767 // update light styles on this submodel
13768 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
13770 model_brush_lightstyleinfo_t *style;
13771 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
13773 if (style->value != r_refdef.scene.lightstylevalue[style->style])
13775 int *list = style->surfacelist;
13776 style->value = r_refdef.scene.lightstylevalue[style->style];
13777 for (j = 0;j < style->numsurfaces;j++)
13778 update[list[j]] = true;
13783 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
13787 R_DrawDebugModel();
13788 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13792 rsurface.lightmaptexture = NULL;
13793 rsurface.deluxemaptexture = NULL;
13794 rsurface.uselightmaptexture = false;
13795 rsurface.texture = NULL;
13796 rsurface.rtlight = NULL;
13797 numsurfacelist = 0;
13798 // add visible surfaces to draw list
13799 for (i = 0;i < model->nummodelsurfaces;i++)
13801 j = model->sortedmodelsurfaces[i];
13802 if (r_refdef.viewcache.world_surfacevisible[j])
13803 r_surfacelist[numsurfacelist++] = surfaces + j;
13805 // update lightmaps if needed
13806 if (model->brushq1.firstrender)
13808 model->brushq1.firstrender = false;
13809 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13811 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
13815 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13816 if (r_refdef.viewcache.world_surfacevisible[j])
13818 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
13820 // don't do anything if there were no surfaces
13821 if (!numsurfacelist)
13823 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13826 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
13828 // add to stats if desired
13829 if (r_speeds.integer && !skysurfaces && !depthonly)
13831 r_refdef.stats.world_surfaces += numsurfacelist;
13832 for (j = 0;j < numsurfacelist;j++)
13833 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
13836 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13839 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
13841 int i, j, endj, flagsmask;
13842 dp_model_t *model = ent->model;
13843 msurface_t *surfaces;
13844 unsigned char *update;
13845 int numsurfacelist = 0;
13849 if (r_maxsurfacelist < model->num_surfaces)
13851 r_maxsurfacelist = model->num_surfaces;
13853 Mem_Free((msurface_t **)r_surfacelist);
13854 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
13857 // if the model is static it doesn't matter what value we give for
13858 // wantnormals and wanttangents, so this logic uses only rules applicable
13859 // to a model, knowing that they are meaningless otherwise
13860 if (ent == r_refdef.scene.worldentity)
13861 RSurf_ActiveWorldEntity();
13862 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
13863 RSurf_ActiveModelEntity(ent, false, false, false);
13865 RSurf_ActiveModelEntity(ent, true, true, true);
13866 else if (depthonly)
13868 switch (vid.renderpath)
13870 case RENDERPATH_GL20:
13871 case RENDERPATH_D3D9:
13872 case RENDERPATH_D3D10:
13873 case RENDERPATH_D3D11:
13874 case RENDERPATH_SOFT:
13875 case RENDERPATH_GLES2:
13876 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
13878 case RENDERPATH_GL13:
13879 case RENDERPATH_GL11:
13880 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
13886 switch (vid.renderpath)
13888 case RENDERPATH_GL20:
13889 case RENDERPATH_D3D9:
13890 case RENDERPATH_D3D10:
13891 case RENDERPATH_D3D11:
13892 case RENDERPATH_SOFT:
13893 case RENDERPATH_GLES2:
13894 RSurf_ActiveModelEntity(ent, true, true, false);
13896 case RENDERPATH_GL13:
13897 case RENDERPATH_GL11:
13898 RSurf_ActiveModelEntity(ent, true, false, false);
13903 surfaces = model->data_surfaces;
13904 update = model->brushq1.lightmapupdateflags;
13906 // update light styles
13907 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
13909 model_brush_lightstyleinfo_t *style;
13910 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
13912 if (style->value != r_refdef.scene.lightstylevalue[style->style])
13914 int *list = style->surfacelist;
13915 style->value = r_refdef.scene.lightstylevalue[style->style];
13916 for (j = 0;j < style->numsurfaces;j++)
13917 update[list[j]] = true;
13922 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
13926 R_DrawDebugModel();
13927 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13931 rsurface.lightmaptexture = NULL;
13932 rsurface.deluxemaptexture = NULL;
13933 rsurface.uselightmaptexture = false;
13934 rsurface.texture = NULL;
13935 rsurface.rtlight = NULL;
13936 numsurfacelist = 0;
13937 // add visible surfaces to draw list
13938 for (i = 0;i < model->nummodelsurfaces;i++)
13939 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
13940 // don't do anything if there were no surfaces
13941 if (!numsurfacelist)
13943 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13946 // update lightmaps if needed
13950 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13955 R_BuildLightMap(ent, surfaces + j);
13960 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13962 R_BuildLightMap(ent, surfaces + j);
13963 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
13965 // add to stats if desired
13966 if (r_speeds.integer && !skysurfaces && !depthonly)
13968 r_refdef.stats.entities_surfaces += numsurfacelist;
13969 for (j = 0;j < numsurfacelist;j++)
13970 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
13973 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13976 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
13978 static texture_t texture;
13979 static msurface_t surface;
13980 const msurface_t *surfacelist = &surface;
13982 // fake enough texture and surface state to render this geometry
13984 texture.update_lastrenderframe = -1; // regenerate this texture
13985 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
13986 texture.currentskinframe = skinframe;
13987 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
13988 texture.offsetmapping = OFFSETMAPPING_OFF;
13989 texture.offsetscale = 1;
13990 texture.specularscalemod = 1;
13991 texture.specularpowermod = 1;
13993 surface.texture = &texture;
13994 surface.num_triangles = numtriangles;
13995 surface.num_firsttriangle = firsttriangle;
13996 surface.num_vertices = numvertices;
13997 surface.num_firstvertex = firstvertex;
14000 rsurface.texture = R_GetCurrentTexture(surface.texture);
14001 rsurface.lightmaptexture = NULL;
14002 rsurface.deluxemaptexture = NULL;
14003 rsurface.uselightmaptexture = false;
14004 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14007 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)
14009 static msurface_t surface;
14010 const msurface_t *surfacelist = &surface;
14012 // fake enough texture and surface state to render this geometry
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);