2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 #include "cl_dyntexture.h"
30 #include "dpsoftrast.h"
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
37 mempool_t *r_main_mempool;
38 rtexturepool_t *r_main_texturepool;
40 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
42 static qboolean r_loadnormalmap;
43 static qboolean r_loadgloss;
45 static qboolean r_loaddds;
46 static qboolean r_savedds;
53 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
55 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
56 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
57 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
58 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
59 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
60 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
62 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
63 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
64 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
65 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
66 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
68 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
69 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
70 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
71 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
72 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
73 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
74 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
75 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
76 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
77 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
78 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
79 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
80 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
81 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
82 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
83 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
84 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
85 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
86 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
87 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
88 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
89 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
90 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
91 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
92 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
93 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
94 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
95 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
97 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
98 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
99 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
101 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
102 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
103 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
104 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
105 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
106 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
107 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
108 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
109 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
110 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
111 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
112 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
113 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
114 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
115 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
116 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
117 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
118 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
119 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
121 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
122 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
123 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
124 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
125 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
126 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
127 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
128 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
130 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
131 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
133 cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
134 cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
135 cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
136 cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
137 cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
139 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
140 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
141 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
143 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
144 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
145 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
146 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
147 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
148 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
149 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
150 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
151 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
152 cvar_t r_glsl_postprocess_uservec1_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec1_enable", "1", "enables postprocessing uservec1 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
153 cvar_t r_glsl_postprocess_uservec2_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec2_enable", "1", "enables postprocessing uservec2 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
154 cvar_t r_glsl_postprocess_uservec3_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec3_enable", "1", "enables postprocessing uservec3 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
155 cvar_t r_glsl_postprocess_uservec4_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec4_enable", "1", "enables postprocessing uservec4 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
157 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
158 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
159 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
160 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
161 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
162 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
164 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
165 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
166 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
167 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
169 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
170 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
171 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
172 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
173 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
174 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
175 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
177 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
178 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
179 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
180 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivalent to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
181 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
182 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
183 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
184 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
185 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
186 cvar_t r_hdr_irisadaptation_fade = {CVAR_SAVE, "r_hdr_irisadaptation_fade", "1", "fade rate at which value adjusts"};
188 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
190 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
192 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
194 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
195 cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
196 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accordingly, 2: Make it a continuous rotation"};
197 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
198 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
199 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "5", "fake perspective effect for SPR_OVERHEAD sprites"};
200 cvar_t r_overheadsprites_pushback = {CVAR_SAVE, "r_overheadsprites_pushback", "15", "how far to pull the SPR_OVERHEAD sprites toward the eye (used to avoid intersections with 3D models)"};
201 cvar_t r_overheadsprites_scalex = {CVAR_SAVE, "r_overheadsprites_scalex", "1", "additional scale for overhead sprites for x axis"};
202 cvar_t r_overheadsprites_scaley = {CVAR_SAVE, "r_overheadsprites_scaley", "1", "additional scale for overhead sprites for y axis"};
204 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
205 cvar_t r_glsl_saturation_redcompensate = {CVAR_SAVE, "r_glsl_saturation_redcompensate", "0", "a 'vampire sight' addition to desaturation effect, does compensation for red color, r_glsl_restart is required"};
207 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "0.5", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
209 extern cvar_t v_glslgamma;
211 extern qboolean v_flipped_state;
213 static struct r_bloomstate_s
218 int bloomwidth, bloomheight;
220 int screentexturewidth, screentextureheight;
221 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
223 int bloomtexturewidth, bloomtextureheight;
224 rtexture_t *texture_bloom;
226 // arrays for rendering the screen passes
227 float screentexcoord2f[8];
228 float bloomtexcoord2f[8];
229 float offsettexcoord2f[8];
231 r_viewport_t viewport;
235 r_waterstate_t r_waterstate;
237 /// shadow volume bsp struct with automatically growing nodes buffer
240 rtexture_t *r_texture_blanknormalmap;
241 rtexture_t *r_texture_white;
242 rtexture_t *r_texture_grey128;
243 rtexture_t *r_texture_black;
244 rtexture_t *r_texture_notexture;
245 rtexture_t *r_texture_whitecube;
246 rtexture_t *r_texture_normalizationcube;
247 rtexture_t *r_texture_fogattenuation;
248 rtexture_t *r_texture_fogheighttexture;
249 rtexture_t *r_texture_gammaramps;
250 unsigned int r_texture_gammaramps_serial;
251 //rtexture_t *r_texture_fogintensity;
252 rtexture_t *r_texture_reflectcube;
254 // TODO: hash lookups?
255 typedef struct cubemapinfo_s
262 int r_texture_numcubemaps;
263 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
265 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
266 unsigned int r_numqueries;
267 unsigned int r_maxqueries;
269 typedef struct r_qwskincache_s
271 char name[MAX_QPATH];
272 skinframe_t *skinframe;
276 static r_qwskincache_t *r_qwskincache;
277 static int r_qwskincache_size;
279 /// vertex coordinates for a quad that covers the screen exactly
280 extern const float r_screenvertex3f[12];
281 extern const float r_d3dscreenvertex3f[12];
282 const float r_screenvertex3f[12] =
289 const float r_d3dscreenvertex3f[12] =
297 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
300 for (i = 0;i < verts;i++)
311 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
314 for (i = 0;i < verts;i++)
324 // FIXME: move this to client?
327 if (gamemode == GAME_NEHAHRA)
329 Cvar_Set("gl_fogenable", "0");
330 Cvar_Set("gl_fogdensity", "0.2");
331 Cvar_Set("gl_fogred", "0.3");
332 Cvar_Set("gl_foggreen", "0.3");
333 Cvar_Set("gl_fogblue", "0.3");
335 r_refdef.fog_density = 0;
336 r_refdef.fog_red = 0;
337 r_refdef.fog_green = 0;
338 r_refdef.fog_blue = 0;
339 r_refdef.fog_alpha = 1;
340 r_refdef.fog_start = 0;
341 r_refdef.fog_end = 16384;
342 r_refdef.fog_height = 1<<30;
343 r_refdef.fog_fadedepth = 128;
344 memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
347 static void R_BuildBlankTextures(void)
349 unsigned char data[4];
350 data[2] = 128; // normal X
351 data[1] = 128; // normal Y
352 data[0] = 255; // normal Z
353 data[3] = 128; // height
354 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
359 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
364 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
369 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
372 static void R_BuildNoTexture(void)
375 unsigned char pix[16][16][4];
376 // this makes a light grey/dark grey checkerboard texture
377 for (y = 0;y < 16;y++)
379 for (x = 0;x < 16;x++)
381 if ((y < 8) ^ (x < 8))
397 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
400 static void R_BuildWhiteCube(void)
402 unsigned char data[6*1*1*4];
403 memset(data, 255, sizeof(data));
404 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
407 static void R_BuildNormalizationCube(void)
411 vec_t s, t, intensity;
414 data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
415 for (side = 0;side < 6;side++)
417 for (y = 0;y < NORMSIZE;y++)
419 for (x = 0;x < NORMSIZE;x++)
421 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
422 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
457 intensity = 127.0f / sqrt(DotProduct(v, v));
458 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
459 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
460 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
461 data[((side*64+y)*64+x)*4+3] = 255;
465 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
469 static void R_BuildFogTexture(void)
473 unsigned char data1[FOGWIDTH][4];
474 //unsigned char data2[FOGWIDTH][4];
477 r_refdef.fogmasktable_start = r_refdef.fog_start;
478 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
479 r_refdef.fogmasktable_range = r_refdef.fogrange;
480 r_refdef.fogmasktable_density = r_refdef.fog_density;
482 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
483 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
485 d = (x * r - r_refdef.fogmasktable_start);
486 if(developer_extra.integer)
487 Con_DPrintf("%f ", d);
489 if (r_fog_exp2.integer)
490 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
492 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
493 if(developer_extra.integer)
494 Con_DPrintf(" : %f ", alpha);
495 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
496 if(developer_extra.integer)
497 Con_DPrintf(" = %f\n", alpha);
498 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
501 for (x = 0;x < FOGWIDTH;x++)
503 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
508 //data2[x][0] = 255 - b;
509 //data2[x][1] = 255 - b;
510 //data2[x][2] = 255 - b;
513 if (r_texture_fogattenuation)
515 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
516 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
520 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
521 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
525 static void R_BuildFogHeightTexture(void)
527 unsigned char *inpixels;
535 strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
536 if (r_refdef.fogheighttexturename[0])
537 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
540 r_refdef.fog_height_tablesize = 0;
541 if (r_texture_fogheighttexture)
542 R_FreeTexture(r_texture_fogheighttexture);
543 r_texture_fogheighttexture = NULL;
544 if (r_refdef.fog_height_table2d)
545 Mem_Free(r_refdef.fog_height_table2d);
546 r_refdef.fog_height_table2d = NULL;
547 if (r_refdef.fog_height_table1d)
548 Mem_Free(r_refdef.fog_height_table1d);
549 r_refdef.fog_height_table1d = NULL;
553 r_refdef.fog_height_tablesize = size;
554 r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
555 r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
556 memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
558 // LordHavoc: now the magic - what is that table2d for? it is a cooked
559 // average fog color table accounting for every fog layer between a point
560 // and the camera. (Note: attenuation is handled separately!)
561 for (y = 0;y < size;y++)
563 for (x = 0;x < size;x++)
569 for (j = x;j <= y;j++)
571 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
577 for (j = x;j >= y;j--)
579 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
584 r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
585 r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
586 r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
587 r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
590 r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
593 //=======================================================================================================================================================
595 static const char *builtinshaderstring =
596 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
597 "// written by Forest 'LordHavoc' Hale\n"
598 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
600 "// GL ES shaders use precision modifiers, standard GL does not\n"
607 "#ifdef VERTEX_SHADER\n"
608 "attribute vec4 Attrib_Position; // vertex\n"
609 "attribute vec4 Attrib_Color; // color\n"
610 "attribute vec4 Attrib_TexCoord0; // material texcoords\n"
611 "attribute vec3 Attrib_TexCoord1; // svector\n"
612 "attribute vec3 Attrib_TexCoord2; // tvector\n"
613 "attribute vec3 Attrib_TexCoord3; // normal\n"
614 "attribute vec4 Attrib_TexCoord4; // lightmap texcoords\n"
616 "varying lowp vec4 VertexColor;\n"
618 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
621 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
622 "#define USELIGHTMAP\n"
624 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
625 "#define USEEYEVECTOR\n"
628 "#ifdef USESHADOWMAP2D\n"
629 "# ifdef GL_EXT_gpu_shader4\n"
630 "# extension GL_EXT_gpu_shader4 : enable\n"
632 "# ifdef GL_ARB_texture_gather\n"
633 "# extension GL_ARB_texture_gather : enable\n"
635 "# ifdef GL_AMD_texture_texture4\n"
636 "# extension GL_AMD_texture_texture4 : enable\n"
641 "//#ifdef USESHADOWSAMPLER\n"
642 "//# extension GL_ARB_shadow : enable\n"
645 "//#ifdef __GLSL_CG_DATA_TYPES\n"
646 "//# define myhalf half\n"
647 "//# define myhalf2 half2\n"
648 "//# define myhalf3 half3\n"
649 "//# define myhalf4 half4\n"
651 "# define myhalf mediump float\n"
652 "# define myhalf2 mediump vec2\n"
653 "# define myhalf3 mediump vec3\n"
654 "# define myhalf4 mediump vec4\n"
657 "#ifdef VERTEX_SHADER\n"
658 "uniform highp mat4 ModelViewProjectionMatrix;\n"
661 "#ifdef MODE_DEPTH_OR_SHADOW\n"
662 "#ifdef VERTEX_SHADER\n"
665 " gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
668 "#else // !MODE_DEPTH_ORSHADOW\n"
673 "#ifdef MODE_SHOWDEPTH\n"
674 "#ifdef VERTEX_SHADER\n"
677 " gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
678 " VertexColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
682 "#ifdef FRAGMENT_SHADER\n"
685 " gl_FragColor = VertexColor;\n"
688 "#else // !MODE_SHOWDEPTH\n"
693 "#ifdef MODE_POSTPROCESS\n"
694 "varying mediump vec2 TexCoord1;\n"
695 "varying mediump vec2 TexCoord2;\n"
697 "#ifdef VERTEX_SHADER\n"
700 " gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
701 " TexCoord1 = Attrib_TexCoord0.xy;\n"
703 " TexCoord2 = Attrib_TexCoord4.xy;\n"
708 "#ifdef FRAGMENT_SHADER\n"
709 "uniform sampler2D Texture_First;\n"
711 "uniform sampler2D Texture_Second;\n"
712 "uniform lowp vec4 BloomColorSubtract;\n"
714 "#ifdef USEGAMMARAMPS\n"
715 "uniform sampler2D Texture_GammaRamps;\n"
717 "#ifdef USESATURATION\n"
718 "uniform lowp float Saturation;\n"
720 "#ifdef USEVIEWTINT\n"
721 "uniform lowp vec4 ViewTintColor;\n"
723 "//uncomment these if you want to use them:\n"
724 "uniform mediump vec4 UserVec1;\n"
725 "uniform mediump vec4 UserVec2;\n"
726 "// uniform mediump vec4 UserVec3;\n"
727 "// uniform mediump vec4 UserVec4;\n"
728 "// uniform highp float ClientTime;\n"
729 "uniform mediump vec2 PixelSize;\n"
732 " gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
734 " gl_FragColor += max(vec4(0,0,0,0), texture2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
736 "#ifdef USEVIEWTINT\n"
737 " gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
740 "#ifdef USEPOSTPROCESSING\n"
741 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
742 "// this code does a blur with the radius specified in the first component of r_glsl_postprocess_uservec1 and blends it using the second component\n"
743 " float sobel = 1.0;\n"
744 " // vec2 ts = textureSize(Texture_First, 0);\n"
745 " // vec2 px = vec2(1/ts.x, 1/ts.y);\n"
746 " vec2 px = PixelSize;\n"
747 " vec3 x1 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
748 " vec3 x2 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, 0.0)).rgb;\n"
749 " vec3 x3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
750 " vec3 x4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
751 " vec3 x5 = texture2D(Texture_First, TexCoord1 + vec2( px.x, 0.0)).rgb;\n"
752 " vec3 x6 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
753 " vec3 y1 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
754 " vec3 y2 = texture2D(Texture_First, TexCoord1 + vec2( 0.0,-px.y)).rgb;\n"
755 " vec3 y3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
756 " vec3 y4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
757 " vec3 y5 = texture2D(Texture_First, TexCoord1 + vec2( 0.0, px.y)).rgb;\n"
758 " vec3 y6 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
759 " float px1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x1);\n"
760 " float px2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), x2);\n"
761 " float px3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x3);\n"
762 " float px4 = 1.0 * dot(vec3(0.3, 0.59, 0.11), x4);\n"
763 " float px5 = 2.0 * dot(vec3(0.3, 0.59, 0.11), x5);\n"
764 " float px6 = 1.0 * dot(vec3(0.3, 0.59, 0.11), x6);\n"
765 " float py1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y1);\n"
766 " float py2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), y2);\n"
767 " float py3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y3);\n"
768 " float py4 = 1.0 * dot(vec3(0.3, 0.59, 0.11), y4);\n"
769 " float py5 = 2.0 * dot(vec3(0.3, 0.59, 0.11), y5);\n"
770 " float py6 = 1.0 * dot(vec3(0.3, 0.59, 0.11), y6);\n"
771 " sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
772 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
773 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
774 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
775 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107, 0.707107)) * UserVec1.y;\n"
776 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990, 0.891007)) * UserVec1.y;\n"
777 " gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
778 " gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + vec3(max(0.0, sobel - UserVec2.z))*UserVec2.y;\n"
781 "#ifdef USESATURATION\n"
782 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
783 " float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
784 " // 'vampire sight' effect, wheres red is compensated\n"
785 " #ifdef SATURATION_REDCOMPENSATE\n"
786 " float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n"
787 " gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
788 " gl_FragColor.r += rboost;\n"
790 " // normal desaturation\n"
791 " //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
792 " gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
796 "#ifdef USEGAMMARAMPS\n"
797 " gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
798 " gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
799 " gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
803 "#else // !MODE_POSTPROCESS\n"
808 "#ifdef MODE_GENERIC\n"
809 "#ifdef USEDIFFUSE\n"
810 "varying mediump vec2 TexCoord1;\n"
812 "#ifdef USESPECULAR\n"
813 "varying mediump vec2 TexCoord2;\n"
815 "#ifdef VERTEX_SHADER\n"
818 " VertexColor = Attrib_Color;\n"
819 "#ifdef USEDIFFUSE\n"
820 " TexCoord1 = Attrib_TexCoord0.xy;\n"
822 "#ifdef USESPECULAR\n"
823 " TexCoord2 = Attrib_TexCoord1.xy;\n"
825 " gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
829 "#ifdef FRAGMENT_SHADER\n"
830 "#ifdef USEDIFFUSE\n"
831 "uniform sampler2D Texture_First;\n"
833 "#ifdef USESPECULAR\n"
834 "uniform sampler2D Texture_Second;\n"
839 "#ifdef USEVIEWTINT\n"
840 " gl_FragColor = VertexColor;\n"
842 " gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
844 "#ifdef USEDIFFUSE\n"
845 " gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
848 "#ifdef USESPECULAR\n"
849 " vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
850 "# ifdef USECOLORMAPPING\n"
851 " gl_FragColor *= tex2;\n"
854 " gl_FragColor += tex2;\n"
856 "# ifdef USEVERTEXTEXTUREBLEND\n"
857 " gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
862 "#else // !MODE_GENERIC\n"
867 "#ifdef MODE_BLOOMBLUR\n"
868 "varying mediump vec2 TexCoord;\n"
869 "#ifdef VERTEX_SHADER\n"
872 " VertexColor = Attrib_Color;\n"
873 " TexCoord = Attrib_TexCoord0.xy;\n"
874 " gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
878 "#ifdef FRAGMENT_SHADER\n"
879 "uniform sampler2D Texture_First;\n"
880 "uniform mediump vec4 BloomBlur_Parameters;\n"
885 " vec2 tc = TexCoord;\n"
886 " vec3 color = texture2D(Texture_First, tc).rgb;\n"
887 " tc += BloomBlur_Parameters.xy;\n"
888 " for (i = 1;i < SAMPLES;i++)\n"
890 " color += texture2D(Texture_First, tc).rgb;\n"
891 " tc += BloomBlur_Parameters.xy;\n"
893 " gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
896 "#else // !MODE_BLOOMBLUR\n"
897 "#ifdef MODE_REFRACTION\n"
898 "varying mediump vec2 TexCoord;\n"
899 "varying highp vec4 ModelViewProjectionPosition;\n"
900 "uniform highp mat4 TexMatrix;\n"
901 "#ifdef VERTEX_SHADER\n"
905 " TexCoord = vec2(TexMatrix * Attrib_TexCoord0);\n"
906 " gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
907 " ModelViewProjectionPosition = gl_Position;\n"
911 "#ifdef FRAGMENT_SHADER\n"
912 "uniform sampler2D Texture_Normal;\n"
913 "uniform sampler2D Texture_Refraction;\n"
914 "uniform sampler2D Texture_Reflection;\n"
916 "uniform mediump vec4 DistortScaleRefractReflect;\n"
917 "uniform mediump vec4 ScreenScaleRefractReflect;\n"
918 "uniform mediump vec4 ScreenCenterRefractReflect;\n"
919 "uniform lowp vec4 RefractColor;\n"
920 "uniform lowp vec4 ReflectColor;\n"
921 "uniform mediump float ReflectFactor;\n"
922 "uniform mediump float ReflectOffset;\n"
926 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
927 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
928 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
929 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
930 " // FIXME temporary hack to detect the case that the reflection\n"
931 " // gets blackened at edges due to leaving the area that contains actual\n"
933 " // Remove this 'ack once we have a better way to stop this thing from\n"
935 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
936 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
937 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
938 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
939 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
940 " gl_FragColor = vec4(texture2D(Texture_Refraction, ScreenTexCoord).rgb, 1.0) * RefractColor;\n"
943 "#else // !MODE_REFRACTION\n"
948 "#ifdef MODE_WATER\n"
949 "varying mediump vec2 TexCoord;\n"
950 "varying highp vec3 EyeVector;\n"
951 "varying highp vec4 ModelViewProjectionPosition;\n"
952 "#ifdef VERTEX_SHADER\n"
953 "uniform highp vec3 EyePosition;\n"
954 "uniform highp mat4 TexMatrix;\n"
958 " TexCoord = vec2(TexMatrix * Attrib_TexCoord0);\n"
959 " vec3 EyeVectorModelSpace = EyePosition - Attrib_Position.xyz;\n"
960 " EyeVector.x = dot(EyeVectorModelSpace, Attrib_TexCoord1.xyz);\n"
961 " EyeVector.y = dot(EyeVectorModelSpace, Attrib_TexCoord2.xyz);\n"
962 " EyeVector.z = dot(EyeVectorModelSpace, Attrib_TexCoord3.xyz);\n"
963 " gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
964 " ModelViewProjectionPosition = gl_Position;\n"
968 "#ifdef FRAGMENT_SHADER\n"
969 "uniform sampler2D Texture_Normal;\n"
970 "uniform sampler2D Texture_Refraction;\n"
971 "uniform sampler2D Texture_Reflection;\n"
973 "uniform mediump vec4 DistortScaleRefractReflect;\n"
974 "uniform mediump vec4 ScreenScaleRefractReflect;\n"
975 "uniform mediump vec4 ScreenCenterRefractReflect;\n"
976 "uniform lowp vec4 RefractColor;\n"
977 "uniform lowp vec4 ReflectColor;\n"
978 "uniform mediump float ReflectFactor;\n"
979 "uniform mediump float ReflectOffset;\n"
980 "uniform highp float ClientTime;\n"
981 "#ifdef USENORMALMAPSCROLLBLEND\n"
982 "uniform highp vec2 NormalmapScrollBlend;\n"
987 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
988 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
989 " vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
990 " //SafeScreenTexCoord = gl_FragCoord.xyxy * vec4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
991 " // slight water animation via 2 layer scrolling (todo: tweak)\n"
992 " #ifdef USENORMALMAPSCROLLBLEND\n"
993 " vec3 normal = texture2D(Texture_Normal, (TexCoord + vec2(0.08, 0.08)*ClientTime*NormalmapScrollBlend.x*0.5)*NormalmapScrollBlend.y).rgb - vec3(1.0);\n"
994 " normal += texture2D(Texture_Normal, (TexCoord + vec2(-0.06, -0.09)*ClientTime*NormalmapScrollBlend.x)*NormalmapScrollBlend.y*0.75).rgb;\n"
995 " vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(normal) + vec3(0.15)).xyxy * DistortScaleRefractReflect;\n"
997 " vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
999 " // FIXME temporary hack to detect the case that the reflection\n"
1000 " // gets blackened at edges due to leaving the area that contains actual\n"
1002 " // Remove this 'ack once we have a better way to stop this thing from\n"
1004 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.005, 0.01)).rgb) / 0.002);\n"
1005 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.005, -0.01)).rgb) / 0.002);\n"
1006 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, 0.01)).rgb) / 0.002);\n"
1007 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, -0.01)).rgb) / 0.002);\n"
1008 " ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
1009 " f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.005, 0.005)).rgb) / 0.002);\n"
1010 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.005, -0.005)).rgb) / 0.002);\n"
1011 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, 0.005)).rgb) / 0.002);\n"
1012 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, -0.005)).rgb) / 0.002);\n"
1013 " ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
1014 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
1015 " gl_FragColor = mix(vec4(texture2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, vec4(texture2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
1018 "#else // !MODE_WATER\n"
1023 "// common definitions between vertex shader and fragment shader:\n"
1025 "varying mediump vec2 TexCoord;\n"
1026 "#ifdef USEVERTEXTEXTUREBLEND\n"
1027 "varying mediump vec2 TexCoord2;\n"
1029 "#ifdef USELIGHTMAP\n"
1030 "varying mediump vec2 TexCoordLightmap;\n"
1033 "#ifdef MODE_LIGHTSOURCE\n"
1034 "varying mediump vec3 CubeVector;\n"
1037 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
1038 "varying mediump vec3 LightVector;\n"
1041 "#ifdef USEEYEVECTOR\n"
1042 "varying highp vec3 EyeVector;\n"
1045 "varying highp vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
1048 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
1049 "varying lowp vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
1050 "varying lowp vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
1051 "varying lowp vec3 VectorR; // direction of R texcoord (surface normal)\n"
1054 "#ifdef USEREFLECTION\n"
1055 "varying highp vec4 ModelViewProjectionPosition;\n"
1057 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1058 "uniform highp vec3 LightPosition;\n"
1059 "varying highp vec4 ModelViewPosition;\n"
1061 "#ifdef MODE_DEFERREDBOUNCELIGHT\n"
1062 "varying highp vec4 ModelViewPosition;\n"
1063 "varying highp vec4 LightOriginInvRadius;\n"
1064 "varying mediump vec4 LightColor;\n"
1067 "#ifdef MODE_LIGHTSOURCE\n"
1068 "uniform highp vec3 LightPosition;\n"
1070 "uniform highp vec3 EyePosition;\n"
1071 "#ifdef MODE_LIGHTDIRECTION\n"
1072 "uniform highp vec3 LightDir;\n"
1074 "uniform highp vec4 FogPlane;\n"
1076 "#ifdef USESHADOWMAPORTHO\n"
1077 "varying mediump vec3 ShadowMapTC;\n"
1080 "#ifdef USEBOUNCEGRID\n"
1081 "varying mediump vec3 BounceGridTexCoord;\n"
1089 "// 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"
1091 "// fragment shader specific:\n"
1092 "#ifdef FRAGMENT_SHADER\n"
1094 "uniform sampler2D Texture_Normal;\n"
1095 "uniform sampler2D Texture_Color;\n"
1096 "uniform sampler2D Texture_Gloss;\n"
1098 "uniform sampler2D Texture_Glow;\n"
1100 "#ifdef USEVERTEXTEXTUREBLEND\n"
1101 "uniform sampler2D Texture_SecondaryNormal;\n"
1102 "uniform sampler2D Texture_SecondaryColor;\n"
1103 "uniform sampler2D Texture_SecondaryGloss;\n"
1105 "uniform sampler2D Texture_SecondaryGlow;\n"
1108 "#ifdef USECOLORMAPPING\n"
1109 "uniform sampler2D Texture_Pants;\n"
1110 "uniform sampler2D Texture_Shirt;\n"
1113 "#ifdef USEFOGHEIGHTTEXTURE\n"
1114 "uniform sampler2D Texture_FogHeightTexture;\n"
1116 "uniform sampler2D Texture_FogMask;\n"
1118 "#ifdef USELIGHTMAP\n"
1119 "uniform sampler2D Texture_Lightmap;\n"
1121 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1122 "uniform sampler2D Texture_Deluxemap;\n"
1124 "#ifdef USEREFLECTION\n"
1125 "uniform sampler2D Texture_Reflection;\n"
1128 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1129 "uniform sampler2D Texture_ScreenDepth;\n"
1130 "uniform sampler2D Texture_ScreenNormalMap;\n"
1132 "#ifdef USEDEFERREDLIGHTMAP\n"
1133 "uniform sampler2D Texture_ScreenDiffuse;\n"
1134 "uniform sampler2D Texture_ScreenSpecular;\n"
1136 "#ifdef MODE_DEFERREDBOUNCELIGHT\n"
1137 "uniform sampler2D Texture_ScreenDepth;\n"
1140 "uniform lowp vec3 Color_Pants;\n"
1141 "uniform lowp vec3 Color_Shirt;\n"
1142 "uniform lowp vec3 FogColor;\n"
1145 "uniform highp float FogRangeRecip;\n"
1146 "uniform highp float FogPlaneViewDist;\n"
1147 "uniform highp float FogHeightFade;\n"
1148 "vec3 FogVertex(vec3 surfacecolor)\n"
1150 " vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
1151 " float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
1153 "#ifdef USEFOGHEIGHTTEXTURE\n"
1154 " vec4 fogheightpixel = texture2D(Texture_FogHeightTexture, vec2(1,1) + vec2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
1155 " fogfrac = fogheightpixel.a;\n"
1156 " return mix(fogheightpixel.rgb * FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1158 "# ifdef USEFOGOUTSIDE\n"
1159 " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1161 " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1163 " return mix(FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1168 "#ifdef USEOFFSETMAPPING\n"
1169 "uniform mediump float OffsetMapping_Scale;\n"
1170 "vec2 OffsetMapping(vec2 TexCoord)\n"
1172 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
1173 " // 14 sample relief mapping: linear search and then binary search\n"
1174 " // this basically steps forward a small amount repeatedly until it finds\n"
1175 " // itself inside solid, then jitters forward and back using decreasing\n"
1176 " // amounts to find the impact\n"
1177 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
1178 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1179 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1180 " vec3 RT = vec3(TexCoord, 1);\n"
1181 " OffsetVector *= 0.1;\n"
1182 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1183 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1184 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1185 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1186 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1187 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1188 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1189 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1190 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1191 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
1192 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
1193 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
1194 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
1195 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1198 " // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1199 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1200 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1201 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1202 " OffsetVector *= 0.5;\n"
1203 " TexCoord += OffsetVector * (1.0 - texture2D(Texture_Normal, TexCoord).a);\n"
1204 " TexCoord += OffsetVector * (1.0 - texture2D(Texture_Normal, TexCoord).a);\n"
1205 " return TexCoord;\n"
1208 "#endif // USEOFFSETMAPPING\n"
1210 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1211 "uniform sampler2D Texture_Attenuation;\n"
1212 "uniform samplerCube Texture_Cube;\n"
1215 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
1217 "#ifdef USESHADOWMAP2D\n"
1218 "# ifdef USESHADOWSAMPLER\n"
1219 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1221 "uniform sampler2D Texture_ShadowMap2D;\n"
1225 "#ifdef USESHADOWMAPVSDCT\n"
1226 "uniform samplerCube Texture_CubeProjection;\n"
1229 "#if defined(USESHADOWMAP2D)\n"
1230 "uniform mediump vec2 ShadowMap_TextureScale;\n"
1231 "uniform mediump vec4 ShadowMap_Parameters;\n"
1234 "#if defined(USESHADOWMAP2D)\n"
1235 "# ifdef USESHADOWMAPORTHO\n"
1236 "# define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n"
1238 "# ifdef USESHADOWMAPVSDCT\n"
1239 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1241 " vec3 adir = abs(dir);\n"
1242 " vec2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
1243 " vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1244 " return vec3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1247 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1249 " vec3 adir = abs(dir);\n"
1250 " float ma = adir.z;\n"
1251 " vec4 proj = vec4(dir, 2.5);\n"
1252 " if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
1253 " if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
1254 " vec2 aparams = ShadowMap_Parameters.xy / ma;\n"
1255 " 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"
1259 "#endif // defined(USESHADOWMAP2D)\n"
1261 "# ifdef USESHADOWMAP2D\n"
1262 "float ShadowMapCompare(vec3 dir)\n"
1264 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1267 "# ifdef USESHADOWSAMPLER\n"
1268 "# ifdef USESHADOWMAPPCF\n"
1269 "# define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r \n"
1270 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1271 " 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"
1273 " f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1276 "# ifdef USESHADOWMAPPCF\n"
1277 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1278 "# ifdef GL_ARB_texture_gather\n"
1279 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1281 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1283 " vec2 offset = fract(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
1284 "# if USESHADOWMAPPCF > 1\n"
1285 " vec4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
1286 " vec4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
1287 " vec4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
1288 " vec4 group4 = step(shadowmaptc.z, texval(-2.0, 0.0));\n"
1289 " vec4 group5 = step(shadowmaptc.z, texval( 0.0, 0.0));\n"
1290 " vec4 group6 = step(shadowmaptc.z, texval( 2.0, 0.0));\n"
1291 " vec4 group7 = step(shadowmaptc.z, texval(-2.0, 2.0));\n"
1292 " vec4 group8 = step(shadowmaptc.z, texval( 0.0, 2.0));\n"
1293 " vec4 group9 = step(shadowmaptc.z, texval( 2.0, 2.0));\n"
1294 " vec4 locols = vec4(group1.ab, group3.ab);\n"
1295 " vec4 hicols = vec4(group7.rg, group9.rg);\n"
1296 " locols.yz += group2.ab;\n"
1297 " hicols.yz += group8.rg;\n"
1298 " vec4 midcols = vec4(group1.rg, group3.rg) + vec4(group7.ab, group9.ab) +\n"
1299 " vec4(group4.rg, group6.rg) + vec4(group4.ab, group6.ab) +\n"
1300 " mix(locols, hicols, offset.y);\n"
1301 " vec4 cols = group5 + vec4(group2.rg, group8.ab);\n"
1302 " cols.xyz += mix(midcols.xyz, midcols.yzw, offset.x);\n"
1303 " f = dot(cols, vec4(1.0/25.0));\n"
1305 " vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1306 " vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1307 " vec4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
1308 " vec4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
1309 " vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1310 " mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1311 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1314 "# ifdef GL_EXT_gpu_shader4\n"
1315 "# define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1317 "# define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r \n"
1319 "# if USESHADOWMAPPCF > 1\n"
1320 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1321 " center *= ShadowMap_TextureScale;\n"
1322 " 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"
1323 " 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"
1324 " 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"
1325 " 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"
1326 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1327 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1329 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1330 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1331 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1332 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1333 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1334 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1338 " f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1341 "# ifdef USESHADOWMAPORTHO\n"
1342 " return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1348 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
1349 "#endif // FRAGMENT_SHADER\n"
1354 "#ifdef MODE_DEFERREDGEOMETRY\n"
1355 "#ifdef VERTEX_SHADER\n"
1356 "uniform highp mat4 TexMatrix;\n"
1357 "#ifdef USEVERTEXTEXTUREBLEND\n"
1358 "uniform highp mat4 BackgroundTexMatrix;\n"
1360 "uniform highp mat4 ModelViewMatrix;\n"
1363 " TexCoord = vec2(TexMatrix * Attrib_TexCoord0);\n"
1364 "#ifdef USEVERTEXTEXTUREBLEND\n"
1365 " VertexColor = Attrib_Color;\n"
1366 " TexCoord2 = vec2(BackgroundTexMatrix * Attrib_TexCoord0);\n"
1369 " // transform unnormalized eye direction into tangent space\n"
1370 "#ifdef USEOFFSETMAPPING\n"
1371 " vec3 EyeVectorModelSpace = EyePosition - Attrib_Position.xyz;\n"
1372 " EyeVector.x = dot(EyeVectorModelSpace, Attrib_TexCoord1.xyz);\n"
1373 " EyeVector.y = dot(EyeVectorModelSpace, Attrib_TexCoord2.xyz);\n"
1374 " EyeVector.z = dot(EyeVectorModelSpace, Attrib_TexCoord3.xyz);\n"
1377 " VectorS = (ModelViewMatrix * vec4(Attrib_TexCoord1.xyz, 0)).xyz;\n"
1378 " VectorT = (ModelViewMatrix * vec4(Attrib_TexCoord2.xyz, 0)).xyz;\n"
1379 " VectorR = (ModelViewMatrix * vec4(Attrib_TexCoord3.xyz, 0)).xyz;\n"
1380 " gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
1382 "#endif // VERTEX_SHADER\n"
1384 "#ifdef FRAGMENT_SHADER\n"
1387 "#ifdef USEOFFSETMAPPING\n"
1388 " // apply offsetmapping\n"
1389 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1390 "#define TexCoord TexCoordOffset\n"
1393 "#ifdef USEALPHAKILL\n"
1394 " if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1398 "#ifdef USEVERTEXTEXTUREBLEND\n"
1399 " float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1400 " float terrainblend = clamp(float(VertexColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1401 " //float terrainblend = min(float(VertexColor.a) * alpha * 2.0, float(1.0));\n"
1402 " //float terrainblend = float(VertexColor.a) * alpha > 0.5;\n"
1405 "#ifdef USEVERTEXTEXTUREBLEND\n"
1406 " vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1407 " float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
1409 " vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1410 " float a = texture2D(Texture_Gloss, TexCoord).a;\n"
1413 " gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
1415 "#endif // FRAGMENT_SHADER\n"
1416 "#else // !MODE_DEFERREDGEOMETRY\n"
1421 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1422 "#ifdef VERTEX_SHADER\n"
1423 "uniform highp mat4 ModelViewMatrix;\n"
1426 " ModelViewPosition = ModelViewMatrix * Attrib_Position;\n"
1427 " gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
1429 "#endif // VERTEX_SHADER\n"
1431 "#ifdef FRAGMENT_SHADER\n"
1432 "uniform highp mat4 ViewToLight;\n"
1433 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1434 "uniform highp vec2 ScreenToDepth;\n"
1435 "uniform myhalf3 DeferredColor_Ambient;\n"
1436 "uniform myhalf3 DeferredColor_Diffuse;\n"
1437 "#ifdef USESPECULAR\n"
1438 "uniform myhalf3 DeferredColor_Specular;\n"
1439 "uniform myhalf SpecularPower;\n"
1441 "uniform myhalf2 PixelToScreenTexCoord;\n"
1444 " // calculate viewspace pixel position\n"
1445 " vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1447 " position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1448 " position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1449 " // decode viewspace pixel normal\n"
1450 " myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1451 " myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1452 " // surfacenormal = pixel normal in viewspace\n"
1453 " // LightVector = pixel to light in viewspace\n"
1454 " // CubeVector = position in lightspace\n"
1455 " // eyevector = pixel to view in viewspace\n"
1456 " vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1457 " myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1458 "#ifdef USEDIFFUSE\n"
1459 " // calculate diffuse shading\n"
1460 " myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1461 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1463 "#ifdef USESPECULAR\n"
1464 " // calculate directional shading\n"
1465 " vec3 eyevector = position * -1.0;\n"
1466 "# ifdef USEEXACTSPECULARMATH\n"
1467 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
1469 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1470 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
1474 "#if defined(USESHADOWMAP2D)\n"
1475 " fade *= ShadowMapCompare(CubeVector);\n"
1478 "#ifdef USEDIFFUSE\n"
1479 " gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1481 " gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1483 "#ifdef USESPECULAR\n"
1484 " gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1486 " gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1489 "# ifdef USECUBEFILTER\n"
1490 " vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1491 " gl_FragData[0].rgb *= cubecolor;\n"
1492 " gl_FragData[1].rgb *= cubecolor;\n"
1495 "#endif // FRAGMENT_SHADER\n"
1496 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1501 "#ifdef MODE_DEFERREDBOUNCELIGHT\n"
1502 "#ifdef VERTEX_SHADER\n"
1503 "uniform highp mat4 ModelViewMatrix;\n"
1506 " ModelViewPosition = ModelViewMatrix * Attrib_Position;\n"
1507 " LightOriginInvRadius.xyz = (ModelViewMatrix * vec4(Attrib_TexCoord0.xyz, 1.0)).xyz;\n"
1508 " LightOriginInvRadius.w = Attrib_TexCoord0.w;\n"
1509 " LightColor = Attrib_Color;\n"
1510 " gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
1512 "#endif // VERTEX_SHADER\n"
1514 "#ifdef FRAGMENT_SHADER\n"
1515 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1516 "uniform highp vec2 ScreenToDepth;\n"
1517 "uniform myhalf2 PixelToScreenTexCoord;\n"
1520 " // calculate viewspace pixel position\n"
1521 " vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1523 " position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1524 " position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1525 " vec3 CubeVector = (position - LightOriginInvRadius.xyz) * LightOriginInvRadius.w;\n"
1526 " gl_FragData[0] = vec4(LightColor.rgb * max(0.0, 1.0 - length(CubeVector)), 1.0);\n"
1528 "#endif // FRAGMENT_SHADER\n"
1529 "#else // !MODE_DEFERREDBOUNCELIGHT\n"
1534 "#ifdef VERTEX_SHADER\n"
1535 "uniform highp mat4 TexMatrix;\n"
1536 "#ifdef USEVERTEXTEXTUREBLEND\n"
1537 "uniform highp mat4 BackgroundTexMatrix;\n"
1539 "#ifdef MODE_LIGHTSOURCE\n"
1540 "uniform highp mat4 ModelToLight;\n"
1542 "#ifdef USESHADOWMAPORTHO\n"
1543 "uniform highp mat4 ShadowMapMatrix;\n"
1545 "#ifdef USEBOUNCEGRID\n"
1546 "uniform highp mat4 BounceGridMatrix;\n"
1550 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1551 " VertexColor = Attrib_Color;\n"
1553 " // copy the surface texcoord\n"
1554 " TexCoord = vec2(TexMatrix * Attrib_TexCoord0);\n"
1555 "#ifdef USEVERTEXTEXTUREBLEND\n"
1556 " TexCoord2 = vec2(BackgroundTexMatrix * Attrib_TexCoord0);\n"
1558 "#ifdef USELIGHTMAP\n"
1559 " TexCoordLightmap = vec2(Attrib_TexCoord4);\n"
1562 "#ifdef USEBOUNCEGRID\n"
1563 " BounceGridTexCoord = vec3(BounceGridMatrix * Attrib_Position);\n"
1566 "#ifdef MODE_LIGHTSOURCE\n"
1567 " // transform vertex position into light attenuation/cubemap space\n"
1568 " // (-1 to +1 across the light box)\n"
1569 " CubeVector = vec3(ModelToLight * Attrib_Position);\n"
1571 "# ifdef USEDIFFUSE\n"
1572 " // transform unnormalized light direction into tangent space\n"
1573 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
1574 " // normalize it per pixel)\n"
1575 " vec3 lightminusvertex = LightPosition - Attrib_Position.xyz;\n"
1576 " LightVector.x = dot(lightminusvertex, Attrib_TexCoord1.xyz);\n"
1577 " LightVector.y = dot(lightminusvertex, Attrib_TexCoord2.xyz);\n"
1578 " LightVector.z = dot(lightminusvertex, Attrib_TexCoord3.xyz);\n"
1582 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1583 " LightVector.x = dot(LightDir, Attrib_TexCoord1.xyz);\n"
1584 " LightVector.y = dot(LightDir, Attrib_TexCoord2.xyz);\n"
1585 " LightVector.z = dot(LightDir, Attrib_TexCoord3.xyz);\n"
1588 " // transform unnormalized eye direction into tangent space\n"
1589 "#ifdef USEEYEVECTOR\n"
1590 " vec3 EyeVectorModelSpace = EyePosition - Attrib_Position.xyz;\n"
1591 " EyeVector.x = dot(EyeVectorModelSpace, Attrib_TexCoord1.xyz);\n"
1592 " EyeVector.y = dot(EyeVectorModelSpace, Attrib_TexCoord2.xyz);\n"
1593 " EyeVector.z = dot(EyeVectorModelSpace, Attrib_TexCoord3.xyz);\n"
1597 " EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - Attrib_Position.xyz;\n"
1598 " EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, Attrib_Position);\n"
1601 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
1602 " VectorS = Attrib_TexCoord1.xyz;\n"
1603 " VectorT = Attrib_TexCoord2.xyz;\n"
1604 " VectorR = Attrib_TexCoord3.xyz;\n"
1607 " // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1608 " gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
1610 "#ifdef USESHADOWMAPORTHO\n"
1611 " ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
1614 "#ifdef USEREFLECTION\n"
1615 " ModelViewProjectionPosition = gl_Position;\n"
1618 "#endif // VERTEX_SHADER\n"
1623 "#ifdef FRAGMENT_SHADER\n"
1624 "#ifdef USEDEFERREDLIGHTMAP\n"
1625 "uniform myhalf2 PixelToScreenTexCoord;\n"
1626 "uniform myhalf3 DeferredMod_Diffuse;\n"
1627 "uniform myhalf3 DeferredMod_Specular;\n"
1629 "uniform myhalf3 Color_Ambient;\n"
1630 "uniform myhalf3 Color_Diffuse;\n"
1631 "uniform myhalf3 Color_Specular;\n"
1632 "uniform myhalf SpecularPower;\n"
1634 "uniform myhalf3 Color_Glow;\n"
1636 "uniform myhalf Alpha;\n"
1637 "#ifdef USEREFLECTION\n"
1638 "uniform mediump vec4 DistortScaleRefractReflect;\n"
1639 "uniform mediump vec4 ScreenScaleRefractReflect;\n"
1640 "uniform mediump vec4 ScreenCenterRefractReflect;\n"
1641 "uniform lowp vec4 ReflectColor;\n"
1643 "#ifdef USEREFLECTCUBE\n"
1644 "uniform highp mat4 ModelToReflectCube;\n"
1645 "uniform sampler2D Texture_ReflectMask;\n"
1646 "uniform samplerCube Texture_ReflectCube;\n"
1648 "#ifdef MODE_LIGHTDIRECTION\n"
1649 "uniform myhalf3 LightColor;\n"
1651 "#ifdef MODE_LIGHTSOURCE\n"
1652 "uniform myhalf3 LightColor;\n"
1654 "#ifdef USEBOUNCEGRID\n"
1655 "uniform sampler3D Texture_BounceGrid;\n"
1656 "uniform float BounceGridIntensity;\n"
1660 "#ifdef USEOFFSETMAPPING\n"
1661 " // apply offsetmapping\n"
1662 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1663 "#define TexCoord TexCoordOffset\n"
1666 " // combine the diffuse textures (base, pants, shirt)\n"
1667 " myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1668 "#ifdef USEALPHAKILL\n"
1669 " if (color.a < 0.5)\n"
1672 " color.a *= Alpha;\n"
1673 "#ifdef USECOLORMAPPING\n"
1674 " color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1676 "#ifdef USEVERTEXTEXTUREBLEND\n"
1677 " myhalf terrainblend = clamp(myhalf(VertexColor.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1678 " //myhalf terrainblend = min(myhalf(VertexColor.a) * color.a * 2.0, myhalf(1.0));\n"
1679 " //myhalf terrainblend = myhalf(VertexColor.a) * color.a > 0.5;\n"
1680 " color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1682 " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1685 " // get the surface normal\n"
1686 "#ifdef USEVERTEXTEXTUREBLEND\n"
1687 " myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1689 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1692 " // get the material colors\n"
1693 " myhalf3 diffusetex = color.rgb;\n"
1694 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1695 "# ifdef USEVERTEXTEXTUREBLEND\n"
1696 " myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1698 " myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
1702 "#ifdef USEREFLECTCUBE\n"
1703 " vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
1704 " vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
1705 " vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
1706 " diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
1712 "#ifdef MODE_LIGHTSOURCE\n"
1713 " // light source\n"
1714 "#ifdef USEDIFFUSE\n"
1715 " myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1716 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1717 " color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1718 "#ifdef USESPECULAR\n"
1719 "#ifdef USEEXACTSPECULARMATH\n"
1720 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1722 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1723 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1725 " color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
1728 " color.rgb = diffusetex * Color_Ambient;\n"
1730 " color.rgb *= LightColor;\n"
1731 " color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1732 "#if defined(USESHADOWMAP2D)\n"
1733 " color.rgb *= ShadowMapCompare(CubeVector);\n"
1735 "# ifdef USECUBEFILTER\n"
1736 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1738 "#endif // MODE_LIGHTSOURCE\n"
1743 "#ifdef MODE_LIGHTDIRECTION\n"
1745 "#ifdef USEDIFFUSE\n"
1746 " myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1748 "#define lightcolor LightColor\n"
1749 "#endif // MODE_LIGHTDIRECTION\n"
1750 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1752 " // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1753 " myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1754 " myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1755 " // convert modelspace light vector to tangentspace\n"
1756 " myhalf3 lightnormal;\n"
1757 " lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1758 " lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1759 " lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1760 " lightnormal = normalize(lightnormal); // VectorS/T/R are not always perfectly normalized, and EXACTSPECULARMATH is very picky about this\n"
1761 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1762 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1763 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1764 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1765 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1766 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1767 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1768 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1769 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1770 " lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1771 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1772 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1774 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1775 " myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1776 " myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1782 "#ifdef MODE_FAKELIGHT\n"
1784 "myhalf3 lightnormal = myhalf3(normalize(EyeVector));\n"
1785 "myhalf3 lightcolor = myhalf3(1.0);\n"
1786 "#endif // MODE_FAKELIGHT\n"
1791 "#ifdef MODE_LIGHTMAP\n"
1792 " color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1793 "#endif // MODE_LIGHTMAP\n"
1794 "#ifdef MODE_VERTEXCOLOR\n"
1795 " color.rgb = diffusetex * (Color_Ambient + myhalf3(VertexColor.rgb) * Color_Diffuse);\n"
1796 "#endif // MODE_VERTEXCOLOR\n"
1797 "#ifdef MODE_FLATCOLOR\n"
1798 " color.rgb = diffusetex * Color_Ambient;\n"
1799 "#endif // MODE_FLATCOLOR\n"
1805 "# ifdef USEDIFFUSE\n"
1806 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1807 "# ifdef USESPECULAR\n"
1808 "# ifdef USEEXACTSPECULARMATH\n"
1809 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1811 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1812 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1814 " color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
1816 " color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1819 " color.rgb = diffusetex * Color_Ambient;\n"
1823 "#ifdef USESHADOWMAPORTHO\n"
1824 " color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
1827 "#ifdef USEDEFERREDLIGHTMAP\n"
1828 " vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1829 " color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1830 " color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1833 "#ifdef USEBOUNCEGRID\n"
1834 " color.rgb += diffusetex * myhalf3(texture3D(Texture_BounceGrid, BounceGridTexCoord)) * BounceGridIntensity;\n"
1838 "#ifdef USEVERTEXTEXTUREBLEND\n"
1839 " color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1841 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1846 " color.rgb = FogVertex(color.rgb);\n"
1849 " // 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"
1850 "#ifdef USEREFLECTION\n"
1851 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1852 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1853 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1854 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1855 " // FIXME temporary hack to detect the case that the reflection\n"
1856 " // gets blackened at edges due to leaving the area that contains actual\n"
1858 " // Remove this 'ack once we have a better way to stop this thing from\n"
1860 " float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1861 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1862 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1863 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1864 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1865 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1868 " gl_FragColor = vec4(color);\n"
1870 "#endif // FRAGMENT_SHADER\n"
1872 "#endif // !MODE_DEFERREDBOUNCELIGHT\n"
1873 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1874 "#endif // !MODE_DEFERREDGEOMETRY\n"
1875 "#endif // !MODE_WATER\n"
1876 "#endif // !MODE_REFRACTION\n"
1877 "#endif // !MODE_BLOOMBLUR\n"
1878 "#endif // !MODE_GENERIC\n"
1879 "#endif // !MODE_POSTPROCESS\n"
1880 "#endif // !MODE_SHOWDEPTH\n"
1881 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1885 =========================================================================================================================================================
1889 =========================================================================================================================================================
1893 =========================================================================================================================================================
1897 =========================================================================================================================================================
1901 =========================================================================================================================================================
1905 =========================================================================================================================================================
1909 =========================================================================================================================================================
1912 const char *builtinhlslshaderstring =
1913 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1914 "// written by Forest 'LordHavoc' Hale\n"
1915 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1917 "// FIXME: we need to get rid of ModelViewProjectionPosition to make room for the texcoord for this\n"
1918 "#if defined(USEREFLECTION)\n"
1919 "#undef USESHADOWMAPORTHO\n"
1922 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
1925 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1926 "#define USELIGHTMAP\n"
1928 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
1929 "#define USEEYEVECTOR\n"
1932 "#ifdef FRAGMENT_SHADER\n"
1934 "//#undef USESHADOWMAPPCF\n"
1935 "//#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1936 "#define texDepth2D(tex,texcoord) dot(tex2D(tex,texcoord).rgb, float3(1.0, 255.0/65536.0, 255.0/16777216.0))\n"
1938 "#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1942 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1943 "#ifdef VERTEX_SHADER\n"
1946 "float4 gl_Vertex : POSITION,\n"
1947 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1948 "out float4 gl_Position : POSITION,\n"
1949 "out float Depth : TEXCOORD0\n"
1952 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1953 " Depth = gl_Position.z;\n"
1957 "#ifdef FRAGMENT_SHADER\n"
1960 "float Depth : TEXCOORD0,\n"
1961 "out float4 gl_FragColor : COLOR\n"
1964 "// float4 temp = float4(Depth,Depth*(65536.0/255.0),Depth*(16777216.0/255.0),0.0);\n"
1965 " float4 temp = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
1966 " temp.yz -= floor(temp.yz);\n"
1967 " gl_FragColor = temp;\n"
1968 "// gl_FragColor = float4(Depth,0,0,0);\n"
1971 "#else // !MODE_DEPTH_ORSHADOW\n"
1976 "#ifdef MODE_SHOWDEPTH\n"
1977 "#ifdef VERTEX_SHADER\n"
1980 "float4 gl_Vertex : POSITION,\n"
1981 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1982 "out float4 gl_Position : POSITION,\n"
1983 "out float4 gl_FrontColor : COLOR0\n"
1986 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1987 " gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1991 "#ifdef FRAGMENT_SHADER\n"
1994 "float4 gl_FrontColor : COLOR0,\n"
1995 "out float4 gl_FragColor : COLOR\n"
1998 " gl_FragColor = gl_FrontColor;\n"
2001 "#else // !MODE_SHOWDEPTH\n"
2006 "#ifdef MODE_POSTPROCESS\n"
2008 "#ifdef VERTEX_SHADER\n"
2011 "float4 gl_Vertex : POSITION,\n"
2012 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2013 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2014 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2015 "out float4 gl_Position : POSITION,\n"
2016 "out float2 TexCoord1 : TEXCOORD0,\n"
2017 "out float2 TexCoord2 : TEXCOORD1\n"
2020 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2021 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
2023 " TexCoord2 = gl_MultiTexCoord4.xy;\n"
2028 "#ifdef FRAGMENT_SHADER\n"
2031 "float2 TexCoord1 : TEXCOORD0,\n"
2032 "float2 TexCoord2 : TEXCOORD1,\n"
2033 "uniform sampler Texture_First : register(s0),\n"
2035 "uniform sampler Texture_Second : register(s1),\n"
2037 "#ifdef USEGAMMARAMPS\n"
2038 "uniform sampler Texture_GammaRamps : register(s2),\n"
2040 "#ifdef USESATURATION\n"
2041 "uniform float Saturation : register(c30),\n"
2043 "#ifdef USEVIEWTINT\n"
2044 "uniform float4 ViewTintColor : register(c41),\n"
2046 "uniform float4 UserVec1 : register(c37),\n"
2047 "uniform float4 UserVec2 : register(c38),\n"
2048 "uniform float4 UserVec3 : register(c39),\n"
2049 "uniform float4 UserVec4 : register(c40),\n"
2050 "uniform float ClientTime : register(c2),\n"
2051 "uniform float2 PixelSize : register(c25),\n"
2052 "uniform float4 BloomColorSubtract : register(c43),\n"
2053 "out float4 gl_FragColor : COLOR\n"
2056 " gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
2058 " gl_FragColor += max(float4(0,0,0,0), tex2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
2060 "#ifdef USEVIEWTINT\n"
2061 " gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
2064 "#ifdef USEPOSTPROCESSING\n"
2065 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
2066 "// 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"
2067 " float sobel = 1.0;\n"
2068 " // float2 ts = textureSize(Texture_First, 0);\n"
2069 " // float2 px = float2(1/ts.x, 1/ts.y);\n"
2070 " float2 px = PixelSize;\n"
2071 " float3 x1 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
2072 " float3 x2 = tex2D(Texture_First, TexCoord1 + float2(-px.x, 0.0)).rgb;\n"
2073 " float3 x3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
2074 " float3 x4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
2075 " float3 x5 = tex2D(Texture_First, TexCoord1 + float2( px.x, 0.0)).rgb;\n"
2076 " float3 x6 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
2077 " float3 y1 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
2078 " float3 y2 = tex2D(Texture_First, TexCoord1 + float2( 0.0,-px.y)).rgb;\n"
2079 " float3 y3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
2080 " float3 y4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
2081 " float3 y5 = tex2D(Texture_First, TexCoord1 + float2( 0.0, px.y)).rgb;\n"
2082 " float3 y6 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
2083 " float px1 = -1.0 * dot(float3(0.3, 0.59, 0.11), x1);\n"
2084 " float px2 = -2.0 * dot(float3(0.3, 0.59, 0.11), x2);\n"
2085 " float px3 = -1.0 * dot(float3(0.3, 0.59, 0.11), x3);\n"
2086 " float px4 = 1.0 * dot(float3(0.3, 0.59, 0.11), x4);\n"
2087 " float px5 = 2.0 * dot(float3(0.3, 0.59, 0.11), x5);\n"
2088 " float px6 = 1.0 * dot(float3(0.3, 0.59, 0.11), x6);\n"
2089 " float py1 = -1.0 * dot(float3(0.3, 0.59, 0.11), y1);\n"
2090 " float py2 = -2.0 * dot(float3(0.3, 0.59, 0.11), y2);\n"
2091 " float py3 = -1.0 * dot(float3(0.3, 0.59, 0.11), y3);\n"
2092 " float py4 = 1.0 * dot(float3(0.3, 0.59, 0.11), y4);\n"
2093 " float py5 = 2.0 * dot(float3(0.3, 0.59, 0.11), y5);\n"
2094 " float py6 = 1.0 * dot(float3(0.3, 0.59, 0.11), y6);\n"
2095 " sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
2096 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
2097 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
2098 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
2099 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107, 0.707107)) * UserVec1.y;\n"
2100 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990, 0.891007)) * UserVec1.y;\n"
2101 " gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
2102 " gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + float3(1,1,1)*max(0.0, sobel - UserVec2.z)*UserVec2.y;\n"
2105 "#ifdef USESATURATION\n"
2106 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
2107 " float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
2108 " // 'vampire sight' effect, wheres red is compensated\n"
2109 " #ifdef SATURATION_REDCOMPENSATE\n"
2110 " float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n"
2111 " gl_FragColor.rgb = lerp(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2112 " gl_FragColor.r += r;\n"
2114 " // normal desaturation\n"
2115 " //gl_FragColor = float3(y,y,y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
2116 " gl_FragColor.rgb = lerp(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2120 "#ifdef USEGAMMARAMPS\n"
2121 " gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
2122 " gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
2123 " gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
2127 "#else // !MODE_POSTPROCESS\n"
2132 "#ifdef MODE_GENERIC\n"
2133 "#ifdef VERTEX_SHADER\n"
2136 "float4 gl_Vertex : POSITION,\n"
2137 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2138 "float4 gl_Color : COLOR0,\n"
2139 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2140 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2141 "out float4 gl_Position : POSITION,\n"
2142 "#ifdef USEDIFFUSE\n"
2143 "out float2 TexCoord1 : TEXCOORD0,\n"
2145 "#ifdef USESPECULAR\n"
2146 "out float2 TexCoord2 : TEXCOORD1,\n"
2148 "out float4 gl_FrontColor : COLOR\n"
2152 " gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2154 " gl_FrontColor = gl_Color; // Cg is forward\n"
2156 "#ifdef USEDIFFUSE\n"
2157 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
2159 "#ifdef USESPECULAR\n"
2160 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
2162 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2166 "#ifdef FRAGMENT_SHADER\n"
2170 "float4 gl_FrontColor : COLOR0,\n"
2171 "float2 TexCoord1 : TEXCOORD0,\n"
2172 "float2 TexCoord2 : TEXCOORD1,\n"
2173 "#ifdef USEDIFFUSE\n"
2174 "uniform sampler Texture_First : register(s0),\n"
2176 "#ifdef USESPECULAR\n"
2177 "uniform sampler Texture_Second : register(s1),\n"
2179 "out float4 gl_FragColor : COLOR\n"
2182 "#ifdef USEVIEWTINT\n"
2183 " gl_FragColor = gl_FrontColor;\n"
2185 " gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
2187 "#ifdef USEDIFFUSE\n"
2188 " gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
2191 "#ifdef USESPECULAR\n"
2192 " float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
2193 "# ifdef USECOLORMAPPING\n"
2194 " gl_FragColor *= tex2;\n"
2197 " gl_FragColor += tex2;\n"
2199 "# ifdef USEVERTEXTEXTUREBLEND\n"
2200 " gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
2205 "#else // !MODE_GENERIC\n"
2210 "#ifdef MODE_BLOOMBLUR\n"
2211 "#ifdef VERTEX_SHADER\n"
2214 "float4 gl_Vertex : POSITION,\n"
2215 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2216 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2217 "out float4 gl_Position : POSITION,\n"
2218 "out float2 TexCoord : TEXCOORD0\n"
2221 " TexCoord = gl_MultiTexCoord0.xy;\n"
2222 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2226 "#ifdef FRAGMENT_SHADER\n"
2230 "float2 TexCoord : TEXCOORD0,\n"
2231 "uniform sampler Texture_First : register(s0),\n"
2232 "uniform float4 BloomBlur_Parameters : register(c1),\n"
2233 "out float4 gl_FragColor : COLOR\n"
2237 " float2 tc = TexCoord;\n"
2238 " float3 color = tex2D(Texture_First, tc).rgb;\n"
2239 " tc += BloomBlur_Parameters.xy;\n"
2240 " for (i = 1;i < SAMPLES;i++)\n"
2242 " color += tex2D(Texture_First, tc).rgb;\n"
2243 " tc += BloomBlur_Parameters.xy;\n"
2245 " gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
2248 "#else // !MODE_BLOOMBLUR\n"
2249 "#ifdef MODE_REFRACTION\n"
2250 "#ifdef VERTEX_SHADER\n"
2253 "float4 gl_Vertex : POSITION,\n"
2254 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2255 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2256 "uniform float4x4 TexMatrix : register(c0),\n"
2257 "uniform float3 EyePosition : register(c24),\n"
2258 "out float4 gl_Position : POSITION,\n"
2259 "out float2 TexCoord : TEXCOORD0,\n"
2260 "out float3 EyeVector : TEXCOORD1,\n"
2261 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2264 " TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2265 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2266 " ModelViewProjectionPosition = gl_Position;\n"
2270 "#ifdef FRAGMENT_SHADER\n"
2273 "float2 TexCoord : TEXCOORD0,\n"
2274 "float3 EyeVector : TEXCOORD1,\n"
2275 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2276 "uniform sampler Texture_Normal : register(s0),\n"
2277 "uniform sampler Texture_Refraction : register(s3),\n"
2278 "uniform sampler Texture_Reflection : register(s7),\n"
2279 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2280 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2281 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2282 "uniform float4 RefractColor : register(c29),\n"
2283 "out float4 gl_FragColor : COLOR\n"
2286 " float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2287 " //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"
2288 " float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2289 " float2 ScreenTexCoord = SafeScreenTexCoord + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy * DistortScaleRefractReflect.xy;\n"
2290 " // FIXME temporary hack to detect the case that the reflection\n"
2291 " // gets blackened at edges due to leaving the area that contains actual\n"
2293 " // Remove this 'ack once we have a better way to stop this thing from\n"
2295 " float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2296 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2297 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2298 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2299 " ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2300 " gl_FragColor = float4(tex2D(Texture_Refraction, ScreenTexCoord).rgb, 1) * RefractColor;\n"
2303 "#else // !MODE_REFRACTION\n"
2308 "#ifdef MODE_WATER\n"
2309 "#ifdef VERTEX_SHADER\n"
2313 "float4 gl_Vertex : POSITION,\n"
2314 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2315 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2316 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2317 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2318 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2319 "uniform float4x4 TexMatrix : register(c0),\n"
2320 "uniform float3 EyePosition : register(c24),\n"
2321 "out float4 gl_Position : POSITION,\n"
2322 "out float2 TexCoord : TEXCOORD0,\n"
2323 "out float3 EyeVector : TEXCOORD1,\n"
2324 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2327 " TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2328 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2329 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2330 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2331 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2332 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2333 " ModelViewProjectionPosition = gl_Position;\n"
2337 "#ifdef FRAGMENT_SHADER\n"
2340 "float2 TexCoord : TEXCOORD0,\n"
2341 "float3 EyeVector : TEXCOORD1,\n"
2342 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2343 "uniform sampler Texture_Normal : register(s0),\n"
2344 "uniform sampler Texture_Refraction : register(s3),\n"
2345 "uniform sampler Texture_Reflection : register(s7),\n"
2346 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2347 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2348 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2349 "uniform float4 RefractColor : register(c29),\n"
2350 "uniform float4 ReflectColor : register(c26),\n"
2351 "uniform float ReflectFactor : register(c27),\n"
2352 "uniform float ReflectOffset : register(c28),\n"
2353 "out float4 gl_FragColor : COLOR\n"
2356 " float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2357 " //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2358 " float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2359 " //SafeScreenTexCoord = gl_FragCoord.xyxy * float4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
2360 " float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy).xyxy * DistortScaleRefractReflect;\n"
2361 " // FIXME temporary hack to detect the case that the reflection\n"
2362 " // gets blackened at edges due to leaving the area that contains actual\n"
2364 " // Remove this 'ack once we have a better way to stop this thing from\n"
2366 " float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2367 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2368 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2369 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2370 " ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2371 " f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2372 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2373 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2374 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2375 " ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2376 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2377 " gl_FragColor = lerp(float4(tex2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, float4(tex2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
2380 "#else // !MODE_WATER\n"
2385 "// 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"
2387 "// fragment shader specific:\n"
2388 "#ifdef FRAGMENT_SHADER\n"
2391 "float3 FogVertex(float3 surfacecolor, float3 FogColor, float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler Texture_FogMask, sampler Texture_FogHeightTexture)\n"
2394 "#ifdef USEFOGHEIGHTTEXTURE\n"
2395 " float4 fogheightpixel = tex2D(Texture_FogHeightTexture, float2(1,1) + float2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
2396 " fogfrac = fogheightpixel.a;\n"
2397 " return lerp(fogheightpixel.rgb * FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2399 "# ifdef USEFOGOUTSIDE\n"
2400 " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2402 " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2404 " return lerp(FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2409 "#ifdef USEOFFSETMAPPING\n"
2410 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler Texture_Normal)\n"
2412 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2413 " // 14 sample relief mapping: linear search and then binary search\n"
2414 " // this basically steps forward a small amount repeatedly until it finds\n"
2415 " // itself inside solid, then jitters forward and back using decreasing\n"
2416 " // amounts to find the impact\n"
2417 " //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2418 " //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2419 " float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2420 " float3 RT = float3(TexCoord, 1);\n"
2421 " OffsetVector *= 0.1;\n"
2422 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2423 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2424 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2425 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2426 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2427 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2428 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2429 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2430 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2431 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
2432 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
2433 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
2434 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
2435 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2438 " // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2439 " //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2440 " //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2441 " float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2442 " OffsetVector *= 0.5;\n"
2443 " TexCoord += OffsetVector * (1.0 - tex2D(Texture_Normal, TexCoord).a);\n"
2444 " TexCoord += OffsetVector * (1.0 - tex2D(Texture_Normal, TexCoord).a);\n"
2445 " return TexCoord;\n"
2448 "#endif // USEOFFSETMAPPING\n"
2450 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2451 "#if defined(USESHADOWMAP2D)\n"
2452 "# ifdef USESHADOWMAPORTHO\n"
2453 "# define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n"
2455 "# ifdef USESHADOWMAPVSDCT\n"
2456 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2458 " float3 adir = abs(dir);\n"
2459 " float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
2460 " float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2461 " return float3(lerp(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2464 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2466 " float3 adir = abs(dir);\n"
2467 " float ma = adir.z;\n"
2468 " float4 proj = float4(dir, 2.5);\n"
2469 " if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
2470 " if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
2472 " 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"
2474 " float2 aparams = ShadowMap_Parameters.xy / ma;\n"
2475 " 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"
2480 "#endif // defined(USESHADOWMAP2D)\n"
2482 "# ifdef USESHADOWMAP2D\n"
2483 "#ifdef USESHADOWMAPVSDCT\n"
2484 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2486 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2489 "#ifdef USESHADOWMAPVSDCT\n"
2490 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2492 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2496 "# ifdef USESHADOWSAMPLER\n"
2497 "# ifdef USESHADOWMAPPCF\n"
2498 "# define texval(x, y) tex2Dproj(Texture_ShadowMap2D, float4(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r \n"
2499 " float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2500 " 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"
2502 " f = tex2Dproj(Texture_ShadowMap2D, float4(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r;\n"
2505 "# ifdef USESHADOWMAPPCF\n"
2506 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2507 "# ifdef GL_ARB_texture_gather\n"
2508 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, int2(x, y))\n"
2510 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)\n"
2512 " float2 offset = frac(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
2513 "# if USESHADOWMAPPCF > 1\n"
2514 " float4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
2515 " float4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
2516 " float4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
2517 " float4 group4 = step(shadowmaptc.z, texval(-2.0, 0.0));\n"
2518 " float4 group5 = step(shadowmaptc.z, texval( 0.0, 0.0));\n"
2519 " float4 group6 = step(shadowmaptc.z, texval( 2.0, 0.0));\n"
2520 " float4 group7 = step(shadowmaptc.z, texval(-2.0, 2.0));\n"
2521 " float4 group8 = step(shadowmaptc.z, texval( 0.0, 2.0));\n"
2522 " float4 group9 = step(shadowmaptc.z, texval( 2.0, 2.0));\n"
2523 " float4 locols = float4(group1.ab, group3.ab);\n"
2524 " float4 hicols = float4(group7.rg, group9.rg);\n"
2525 " locols.yz += group2.ab;\n"
2526 " hicols.yz += group8.rg;\n"
2527 " float4 midcols = float4(group1.rg, group3.rg) + float4(group7.ab, group9.ab) +\n"
2528 " float4(group4.rg, group6.rg) + float4(group4.ab, group6.ab) +\n"
2529 " lerp(locols, hicols, offset.y);\n"
2530 " float4 cols = group5 + float4(group2.rg, group8.ab);\n"
2531 " cols.xyz += lerp(midcols.xyz, midcols.yzw, offset.x);\n"
2532 " f = dot(cols, float4(1.0/25.0));\n"
2534 " float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2535 " float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2536 " float4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
2537 " float4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
2538 " float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2539 " lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2540 " f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2543 "# ifdef GL_EXT_gpu_shader4\n"
2544 "# define texval(x, y) tex2DOffset(Texture_ShadowMap2D, center, int2(x, y)).r\n"
2546 "# define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale).r \n"
2548 "# if USESHADOWMAPPCF > 1\n"
2549 " float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2550 " center *= ShadowMap_TextureScale;\n"
2551 " 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"
2552 " 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"
2553 " 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"
2554 " 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"
2555 " float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2556 " f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2558 " float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2559 " float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2560 " float3 row2 = step(shadowmaptc.z, float3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
2561 " float3 row3 = step(shadowmaptc.z, float3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
2562 " float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2563 " f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25,0.25));\n"
2567 " f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2570 "# ifdef USESHADOWMAPORTHO\n"
2571 " return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2577 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
2578 "#endif // FRAGMENT_SHADER\n"
2583 "#ifdef MODE_DEFERREDGEOMETRY\n"
2584 "#ifdef VERTEX_SHADER\n"
2587 "float4 gl_Vertex : POSITION,\n"
2588 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2589 "#ifdef USEVERTEXTEXTUREBLEND\n"
2590 "float4 gl_Color : COLOR0,\n"
2592 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2593 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2594 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2595 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2596 "uniform float4x4 TexMatrix : register(c0),\n"
2597 "#ifdef USEVERTEXTEXTUREBLEND\n"
2598 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2600 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2601 "#ifdef USEOFFSETMAPPING\n"
2602 "uniform float3 EyePosition : register(c24),\n"
2604 "out float4 gl_Position : POSITION,\n"
2605 "#ifdef USEVERTEXTEXTUREBLEND\n"
2606 "out float4 gl_FrontColor : COLOR,\n"
2608 "out float4 TexCoordBoth : TEXCOORD0,\n"
2609 "#ifdef USEOFFSETMAPPING\n"
2610 "out float3 EyeVector : TEXCOORD2,\n"
2612 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2613 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2614 "out float4 VectorR : TEXCOORD7 // direction of R texcoord (surface normal), Depth value\n"
2617 " TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2618 "#ifdef USEVERTEXTEXTUREBLEND\n"
2620 " gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2622 " gl_FrontColor = gl_Color; // Cg is forward\n"
2624 " TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2627 " // transform unnormalized eye direction into tangent space\n"
2628 "#ifdef USEOFFSETMAPPING\n"
2629 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2630 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2631 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2632 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2635 " VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2636 " VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2637 " VectorR.xyz = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2638 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2639 " VectorR.w = gl_Position.z;\n"
2641 "#endif // VERTEX_SHADER\n"
2643 "#ifdef FRAGMENT_SHADER\n"
2646 "float4 TexCoordBoth : TEXCOORD0,\n"
2647 "float3 EyeVector : TEXCOORD2,\n"
2648 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2649 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2650 "float4 VectorR : TEXCOORD7, // direction of R texcoord (surface normal), Depth value\n"
2651 "uniform sampler Texture_Normal : register(s0),\n"
2652 "#ifdef USEALPHAKILL\n"
2653 "uniform sampler Texture_Color : register(s1),\n"
2655 "uniform sampler Texture_Gloss : register(s2),\n"
2656 "#ifdef USEVERTEXTEXTUREBLEND\n"
2657 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2658 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2660 "#ifdef USEOFFSETMAPPING\n"
2661 "uniform float OffsetMapping_Scale : register(c24),\n"
2663 "uniform half SpecularPower : register(c36),\n"
2665 "out float4 gl_FragData0 : COLOR0,\n"
2666 "out float4 gl_FragData1 : COLOR1\n"
2668 "out float4 gl_FragColor : COLOR\n"
2672 " float2 TexCoord = TexCoordBoth.xy;\n"
2673 "#ifdef USEOFFSETMAPPING\n"
2674 " // apply offsetmapping\n"
2675 " float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2676 "#define TexCoord TexCoordOffset\n"
2679 "#ifdef USEALPHAKILL\n"
2680 " if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2684 "#ifdef USEVERTEXTEXTUREBLEND\n"
2685 " float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2686 " float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2687 " //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2688 " //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2691 "#ifdef USEVERTEXTEXTUREBLEND\n"
2692 " float3 surfacenormal = lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend) - float3(0.5, 0.5, 0.5);\n"
2693 " float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2).a, tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
2695 " float3 surfacenormal = tex2D(Texture_Normal, TexCoord).rgb - float3(0.5, 0.5, 0.5);\n"
2696 " float a = tex2D(Texture_Gloss, TexCoord).a;\n"
2700 " 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"
2701 " float Depth = VectorR.w / 256.0;\n"
2702 " float4 depthcolor = float4(Depth,Depth*65536.0/255.0,Depth*16777216.0/255.0,0.0);\n"
2703 "// float4 depthcolor = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
2704 " depthcolor.yz -= floor(depthcolor.yz);\n"
2705 " gl_FragData1 = depthcolor;\n"
2707 " gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), a);\n"
2710 "#endif // FRAGMENT_SHADER\n"
2711 "#else // !MODE_DEFERREDGEOMETRY\n"
2716 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2717 "#ifdef VERTEX_SHADER\n"
2720 "float4 gl_Vertex : POSITION,\n"
2721 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2722 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2723 "out float4 gl_Position : POSITION,\n"
2724 "out float4 ModelViewPosition : TEXCOORD0\n"
2727 " ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2728 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2730 "#endif // VERTEX_SHADER\n"
2732 "#ifdef FRAGMENT_SHADER\n"
2736 "float2 Pixel : VPOS,\n"
2738 "float2 Pixel : WPOS,\n"
2740 "float4 ModelViewPosition : TEXCOORD0,\n"
2741 "uniform float4x4 ViewToLight : register(c44),\n"
2742 "uniform float2 ScreenToDepth : register(c33), // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2743 "uniform float3 LightPosition : register(c23),\n"
2744 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
2745 "uniform half3 DeferredColor_Ambient : register(c9),\n"
2746 "uniform half3 DeferredColor_Diffuse : register(c10),\n"
2747 "#ifdef USESPECULAR\n"
2748 "uniform half3 DeferredColor_Specular : register(c11),\n"
2749 "uniform half SpecularPower : register(c36),\n"
2751 "uniform sampler Texture_Attenuation : register(s9),\n"
2752 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2753 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2755 "#ifdef USECUBEFILTER\n"
2756 "uniform samplerCUBE Texture_Cube : register(s10),\n"
2759 "#ifdef USESHADOWMAP2D\n"
2760 "# ifdef USESHADOWSAMPLER\n"
2761 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2763 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2767 "#ifdef USESHADOWMAPVSDCT\n"
2768 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
2771 "#if defined(USESHADOWMAP2D)\n"
2772 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
2773 "uniform float4 ShadowMap_Parameters : register(c34),\n"
2776 "out float4 gl_FragData0 : COLOR0,\n"
2777 "out float4 gl_FragData1 : COLOR1\n"
2780 " // calculate viewspace pixel position\n"
2781 " float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2782 " //ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2783 " float3 position;\n"
2785 " position.z = texDepth2D(Texture_ScreenDepth, ScreenTexCoord) * 256.0;\n"
2787 " position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2789 " position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2790 " // decode viewspace pixel normal\n"
2791 " half4 normalmap = half4(tex2D(Texture_ScreenNormalMap, ScreenTexCoord));\n"
2792 " half3 surfacenormal = half3(normalize(normalmap.rgb - half3(0.5,0.5,0.5)));\n"
2793 " // surfacenormal = pixel normal in viewspace\n"
2794 " // LightVector = pixel to light in viewspace\n"
2795 " // CubeVector = position in lightspace\n"
2796 " // eyevector = pixel to view in viewspace\n"
2797 " float3 CubeVector = mul(ViewToLight, float4(position,1)).xyz;\n"
2798 " half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
2799 "#ifdef USEDIFFUSE\n"
2800 " // calculate diffuse shading\n"
2801 " half3 lightnormal = half3(normalize(LightPosition - position));\n"
2802 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2804 "#ifdef USESPECULAR\n"
2805 " // calculate directional shading\n"
2806 " float3 eyevector = position * -1.0;\n"
2807 "# ifdef USEEXACTSPECULARMATH\n"
2808 " half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a));\n"
2810 " half3 specularnormal = half3(normalize(lightnormal + half3(normalize(eyevector))));\n"
2811 " half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a));\n"
2815 "#if defined(USESHADOWMAP2D)\n"
2816 " fade *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2817 "#ifdef USESHADOWMAPVSDCT\n"
2818 ", Texture_CubeProjection\n"
2823 "#ifdef USEDIFFUSE\n"
2824 " gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2826 " gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2828 "#ifdef USESPECULAR\n"
2829 " gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2831 " gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2834 "# ifdef USECUBEFILTER\n"
2835 " float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2836 " gl_FragData0.rgb *= cubecolor;\n"
2837 " gl_FragData1.rgb *= cubecolor;\n"
2840 "#endif // FRAGMENT_SHADER\n"
2841 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2846 "#ifdef VERTEX_SHADER\n"
2849 "float4 gl_Vertex : POSITION,\n"
2850 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2851 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2852 "float4 gl_Color : COLOR0,\n"
2854 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2855 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2856 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2857 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2858 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2860 "uniform float3 EyePosition : register(c24),\n"
2861 "uniform float4x4 TexMatrix : register(c0),\n"
2862 "#ifdef USEVERTEXTEXTUREBLEND\n"
2863 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2865 "#ifdef MODE_LIGHTSOURCE\n"
2866 "uniform float4x4 ModelToLight : register(c20),\n"
2868 "#ifdef MODE_LIGHTSOURCE\n"
2869 "uniform float3 LightPosition : register(c27),\n"
2871 "#ifdef MODE_LIGHTDIRECTION\n"
2872 "uniform float3 LightDir : register(c26),\n"
2874 "uniform float4 FogPlane : register(c25),\n"
2875 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2876 "uniform float3 LightPosition : register(c27),\n"
2878 "#ifdef USESHADOWMAPORTHO\n"
2879 "uniform float4x4 ShadowMapMatrix : register(c16),\n"
2881 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2882 "out float4 gl_FrontColor : COLOR,\n"
2884 "out float4 TexCoordBoth : TEXCOORD0,\n"
2885 "#ifdef USELIGHTMAP\n"
2886 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2888 "#ifdef USEEYEVECTOR\n"
2889 "out float3 EyeVector : TEXCOORD2,\n"
2891 "#ifdef USEREFLECTION\n"
2892 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2895 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2897 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE) || defined(USEDIFFUSE)\n"
2898 "out float3 LightVector : TEXCOORD1,\n"
2900 "#ifdef MODE_LIGHTSOURCE\n"
2901 "out float3 CubeVector : TEXCOORD3,\n"
2903 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2904 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2905 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2906 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2908 "#ifdef USESHADOWMAPORTHO\n"
2909 "out float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2911 "out float4 gl_Position : POSITION\n"
2914 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2916 " gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2918 " gl_FrontColor = gl_Color; // Cg is forward\n"
2921 " // copy the surface texcoord\n"
2922 " TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2923 "#ifdef USEVERTEXTEXTUREBLEND\n"
2924 " TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2926 "#ifdef USELIGHTMAP\n"
2927 " TexCoordLightmap = gl_MultiTexCoord4.xy;\n"
2930 "#ifdef MODE_LIGHTSOURCE\n"
2931 " // transform vertex position into light attenuation/cubemap space\n"
2932 " // (-1 to +1 across the light box)\n"
2933 " CubeVector = mul(ModelToLight, gl_Vertex).xyz;\n"
2935 "# ifdef USEDIFFUSE\n"
2936 " // transform unnormalized light direction into tangent space\n"
2937 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
2938 " // normalize it per pixel)\n"
2939 " float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2940 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2941 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2942 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2946 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2947 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2948 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2949 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2952 " // transform unnormalized eye direction into tangent space\n"
2953 "#ifdef USEEYEVECTOR\n"
2954 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2955 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2956 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2957 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2961 " EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2962 " EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2965 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2966 " VectorS = gl_MultiTexCoord1.xyz;\n"
2967 " VectorT = gl_MultiTexCoord2.xyz;\n"
2968 " VectorR = gl_MultiTexCoord3.xyz;\n"
2971 " // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2972 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2974 "#ifdef USESHADOWMAPORTHO\n"
2975 " ShadowMapTC = mul(ShadowMapMatrix, gl_Position).xyz;\n"
2978 "#ifdef USEREFLECTION\n"
2979 " ModelViewProjectionPosition = gl_Position;\n"
2982 "#endif // VERTEX_SHADER\n"
2987 "#ifdef FRAGMENT_SHADER\n"
2990 "#ifdef USEDEFERREDLIGHTMAP\n"
2992 "float2 Pixel : VPOS,\n"
2994 "float2 Pixel : WPOS,\n"
2997 "float4 gl_FrontColor : COLOR,\n"
2998 "float4 TexCoordBoth : TEXCOORD0,\n"
2999 "#ifdef USELIGHTMAP\n"
3000 "float2 TexCoordLightmap : TEXCOORD1,\n"
3002 "#ifdef USEEYEVECTOR\n"
3003 "float3 EyeVector : TEXCOORD2,\n"
3005 "#ifdef USEREFLECTION\n"
3006 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
3009 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
3011 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
3012 "float3 LightVector : TEXCOORD1,\n"
3014 "#ifdef MODE_LIGHTSOURCE\n"
3015 "float3 CubeVector : TEXCOORD3,\n"
3017 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
3018 "float4 ModelViewPosition : TEXCOORD0,\n"
3020 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
3021 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
3022 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
3023 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
3025 "#ifdef USESHADOWMAPORTHO\n"
3026 "float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
3029 "uniform sampler Texture_Normal : register(s0),\n"
3030 "uniform sampler Texture_Color : register(s1),\n"
3031 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3032 "uniform sampler Texture_Gloss : register(s2),\n"
3035 "uniform sampler Texture_Glow : register(s3),\n"
3037 "#ifdef USEVERTEXTEXTUREBLEND\n"
3038 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
3039 "uniform sampler Texture_SecondaryColor : register(s5),\n"
3040 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3041 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
3044 "uniform sampler Texture_SecondaryGlow : register(s7),\n"
3047 "#ifdef USECOLORMAPPING\n"
3048 "uniform sampler Texture_Pants : register(s4),\n"
3049 "uniform sampler Texture_Shirt : register(s7),\n"
3052 "uniform sampler Texture_FogHeightTexture : register(s14),\n"
3053 "uniform sampler Texture_FogMask : register(s8),\n"
3055 "#ifdef USELIGHTMAP\n"
3056 "uniform sampler Texture_Lightmap : register(s9),\n"
3058 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
3059 "uniform sampler Texture_Deluxemap : register(s10),\n"
3061 "#ifdef USEREFLECTION\n"
3062 "uniform sampler Texture_Reflection : register(s7),\n"
3065 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
3066 "uniform sampler Texture_ScreenDepth : register(s13),\n"
3067 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
3069 "#ifdef USEDEFERREDLIGHTMAP\n"
3070 "uniform sampler Texture_ScreenDepth : register(s13),\n"
3071 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
3072 "uniform sampler Texture_ScreenDiffuse : register(s11),\n"
3073 "uniform sampler Texture_ScreenSpecular : register(s12),\n"
3076 "#ifdef USECOLORMAPPING\n"
3077 "uniform half3 Color_Pants : register(c7),\n"
3078 "uniform half3 Color_Shirt : register(c8),\n"
3081 "uniform float3 FogColor : register(c16),\n"
3082 "uniform float FogRangeRecip : register(c20),\n"
3083 "uniform float FogPlaneViewDist : register(c19),\n"
3084 "uniform float FogHeightFade : register(c17),\n"
3087 "#ifdef USEOFFSETMAPPING\n"
3088 "uniform float OffsetMapping_Scale : register(c24),\n"
3091 "#ifdef USEDEFERREDLIGHTMAP\n"
3092 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
3093 "uniform half3 DeferredMod_Diffuse : register(c12),\n"
3094 "uniform half3 DeferredMod_Specular : register(c13),\n"
3096 "uniform half3 Color_Ambient : register(c3),\n"
3097 "uniform half3 Color_Diffuse : register(c4),\n"
3098 "uniform half3 Color_Specular : register(c5),\n"
3099 "uniform half SpecularPower : register(c36),\n"
3101 "uniform half3 Color_Glow : register(c6),\n"
3103 "uniform half Alpha : register(c0),\n"
3104 "#ifdef USEREFLECTION\n"
3105 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
3106 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
3107 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
3108 "uniform half4 ReflectColor : register(c26),\n"
3110 "#ifdef USEREFLECTCUBE\n"
3111 "uniform float4x4 ModelToReflectCube : register(c48),\n"
3112 "uniform sampler Texture_ReflectMask : register(s5),\n"
3113 "uniform samplerCUBE Texture_ReflectCube : register(s6),\n"
3115 "#ifdef MODE_LIGHTDIRECTION\n"
3116 "uniform half3 LightColor : register(c21),\n"
3118 "#ifdef MODE_LIGHTSOURCE\n"
3119 "uniform half3 LightColor : register(c21),\n"
3122 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
3123 "uniform sampler Texture_Attenuation : register(s9),\n"
3124 "uniform samplerCUBE Texture_Cube : register(s10),\n"
3127 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
3129 "#ifdef USESHADOWMAP2D\n"
3130 "# ifdef USESHADOWSAMPLER\n"
3131 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
3133 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
3137 "#ifdef USESHADOWMAPVSDCT\n"
3138 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
3141 "#if defined(USESHADOWMAP2D)\n"
3142 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
3143 "uniform float4 ShadowMap_Parameters : register(c34),\n"
3145 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
3147 "out float4 gl_FragColor : COLOR\n"
3150 " float2 TexCoord = TexCoordBoth.xy;\n"
3151 "#ifdef USEVERTEXTEXTUREBLEND\n"
3152 " float2 TexCoord2 = TexCoordBoth.zw;\n"
3154 "#ifdef USEOFFSETMAPPING\n"
3155 " // apply offsetmapping\n"
3156 " float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
3157 "#define TexCoord TexCoordOffset\n"
3160 " // combine the diffuse textures (base, pants, shirt)\n"
3161 " half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
3162 "#ifdef USEALPHAKILL\n"
3163 " if (color.a < 0.5)\n"
3166 " color.a *= Alpha;\n"
3167 "#ifdef USECOLORMAPPING\n"
3168 " color.rgb += half3(tex2D(Texture_Pants, TexCoord).rgb) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord).rgb) * Color_Shirt;\n"
3170 "#ifdef USEVERTEXTEXTUREBLEND\n"
3171 " half terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
3172 " //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
3173 " //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
3174 " color.rgb = half3(lerp(tex2D(Texture_SecondaryColor, TexCoord2).rgb, float3(color.rgb), terrainblend));\n"
3176 " //color = half4(lerp(float4(1, 0, 0, 1), color, terrainblend));\n"
3179 " // get the surface normal\n"
3180 "#ifdef USEVERTEXTEXTUREBLEND\n"
3181 " half3 surfacenormal = normalize(half3(lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend)) - half3(0.5, 0.5, 0.5));\n"
3183 " half3 surfacenormal = half3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5, 0.5, 0.5)));\n"
3186 " // get the material colors\n"
3187 " half3 diffusetex = color.rgb;\n"
3188 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3189 "# ifdef USEVERTEXTEXTUREBLEND\n"
3190 " half4 glosstex = half4(lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord), terrainblend));\n"
3192 " half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
3196 "#ifdef USEREFLECTCUBE\n"
3197 " float3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
3198 " float3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
3199 " float3 ReflectCubeTexCoord = mul(ModelToReflectCube, float4(ModelReflectVector, 0)).xyz;\n"
3200 " diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord).rgb) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord).rgb);\n"
3206 "#ifdef MODE_LIGHTSOURCE\n"
3207 " // light source\n"
3208 "#ifdef USEDIFFUSE\n"
3209 " half3 lightnormal = half3(normalize(LightVector));\n"
3210 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3211 " color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
3212 "#ifdef USESPECULAR\n"
3213 "#ifdef USEEXACTSPECULARMATH\n"
3214 " half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3216 " half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3217 " half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3219 " color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
3222 " color.rgb = diffusetex * Color_Ambient;\n"
3224 " color.rgb *= LightColor;\n"
3225 " color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
3226 "#if defined(USESHADOWMAP2D)\n"
3227 " color.rgb *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3228 "#ifdef USESHADOWMAPVSDCT\n"
3229 ", Texture_CubeProjection\n"
3234 "# ifdef USECUBEFILTER\n"
3235 " color.rgb *= half3(texCUBE(Texture_Cube, CubeVector).rgb);\n"
3238 "#ifdef USESHADOWMAP2D\n"
3239 "#ifdef USESHADOWMAPVSDCT\n"
3240 "// float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters, Texture_CubeProjection);\n"
3242 "// float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters);\n"
3244 "// color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3245 "// color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3246 "// color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3247 "// color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3248 "// color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3249 "// color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3250 "// color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3251 "// color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3252 "// color.r = half(shadowmaptc.z - texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3253 "// color.r = half(shadowmaptc.z);\n"
3254 "// color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3255 "// color.r = half(shadowmaptc.z);\n"
3257 "// color.rgb = abs(CubeVector);\n"
3259 "// color.rgb = half3(1,1,1);\n"
3260 "#endif // MODE_LIGHTSOURCE\n"
3265 "#ifdef MODE_LIGHTDIRECTION\n"
3267 "#ifdef USEDIFFUSE\n"
3268 " half3 lightnormal = half3(normalize(LightVector));\n"
3270 "#define lightcolor LightColor\n"
3271 "#endif // MODE_LIGHTDIRECTION\n"
3272 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3274 " // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3275 " half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3276 " half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3277 " // convert modelspace light vector to tangentspace\n"
3278 " half3 lightnormal;\n"
3279 " lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3280 " lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3281 " lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3282 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3283 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3284 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3285 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3286 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3287 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3288 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3289 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3290 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3291 " lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3292 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3293 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3295 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3296 " half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3297 " half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3303 "#ifdef MODE_FAKELIGHT\n"
3305 "half3 lightnormal = half3(normalize(EyeVector));\n"
3306 "half3 lightcolor = half3(1.0,1.0,1.0);\n"
3307 "#endif // MODE_FAKELIGHT\n"
3312 "#ifdef MODE_LIGHTMAP\n"
3313 " color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb) * Color_Diffuse);\n"
3314 "#endif // MODE_LIGHTMAP\n"
3315 "#ifdef MODE_VERTEXCOLOR\n"
3316 " color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3317 "#endif // MODE_VERTEXCOLOR\n"
3318 "#ifdef MODE_FLATCOLOR\n"
3319 " color.rgb = diffusetex * Color_Ambient;\n"
3320 "#endif // MODE_FLATCOLOR\n"
3326 "# ifdef USEDIFFUSE\n"
3327 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3328 "# ifdef USESPECULAR\n"
3329 "# ifdef USEEXACTSPECULARMATH\n"
3330 " half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3332 " half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3333 " half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3335 " color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3337 " color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3340 " color.rgb = diffusetex * Color_Ambient;\n"
3344 "#ifdef USESHADOWMAPORTHO\n"
3345 " color.rgb *= half(ShadowMapCompare(ShadowMapTC, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale));\n"
3348 "#ifdef USEDEFERREDLIGHTMAP\n"
3349 " float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3350 " color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord).rgb) * DeferredMod_Diffuse;\n"
3351 " color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord).rgb) * DeferredMod_Specular;\n"
3352 "// color.rgb = half3(tex2D(Texture_ScreenDepth, ScreenTexCoord).rgb);\n"
3353 "// color.r = half(texDepth2D(Texture_ScreenDepth, ScreenTexCoord)) * 1.0;\n"
3357 "#ifdef USEVERTEXTEXTUREBLEND\n"
3358 " color.rgb += half3(lerp(tex2D(Texture_SecondaryGlow, TexCoord2).rgb, tex2D(Texture_Glow, TexCoord).rgb, terrainblend)) * Color_Glow;\n"
3360 " color.rgb += half3(tex2D(Texture_Glow, TexCoord).rgb) * Color_Glow;\n"
3365 " color.rgb = FogVertex(color.rgb, FogColor, EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask, Texture_FogHeightTexture);\n"
3368 " // 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"
3369 "#ifdef USEREFLECTION\n"
3370 " float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3371 " //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3372 " float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3373 " float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.zw;\n"
3374 " // FIXME temporary hack to detect the case that the reflection\n"
3375 " // gets blackened at edges due to leaving the area that contains actual\n"
3377 " // Remove this 'ack once we have a better way to stop this thing from\n"
3379 " float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3380 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3381 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3382 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3383 " ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3384 " color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord).rgb) * ReflectColor.rgb, ReflectColor.a);\n"
3387 " gl_FragColor = float4(color);\n"
3389 "#endif // FRAGMENT_SHADER\n"
3391 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3392 "#endif // !MODE_DEFERREDGEOMETRY\n"
3393 "#endif // !MODE_WATER\n"
3394 "#endif // !MODE_REFRACTION\n"
3395 "#endif // !MODE_BLOOMBLUR\n"
3396 "#endif // !MODE_GENERIC\n"
3397 "#endif // !MODE_POSTPROCESS\n"
3398 "#endif // !MODE_SHOWDEPTH\n"
3399 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3402 char *glslshaderstring = NULL;
3403 char *hlslshaderstring = NULL;
3405 //=======================================================================================================================================================
3407 typedef struct shaderpermutationinfo_s
3409 const char *pretext;
3412 shaderpermutationinfo_t;
3414 typedef struct shadermodeinfo_s
3416 const char *vertexfilename;
3417 const char *geometryfilename;
3418 const char *fragmentfilename;
3419 const char *pretext;
3424 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3425 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3427 {"#define USEDIFFUSE\n", " diffuse"},
3428 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3429 {"#define USEVIEWTINT\n", " viewtint"},
3430 {"#define USECOLORMAPPING\n", " colormapping"},
3431 {"#define USESATURATION\n", " saturation"},
3432 {"#define USEFOGINSIDE\n", " foginside"},
3433 {"#define USEFOGOUTSIDE\n", " fogoutside"},
3434 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
3435 {"#define USEGAMMARAMPS\n", " gammaramps"},
3436 {"#define USECUBEFILTER\n", " cubefilter"},
3437 {"#define USEGLOW\n", " glow"},
3438 {"#define USEBLOOM\n", " bloom"},
3439 {"#define USESPECULAR\n", " specular"},
3440 {"#define USEPOSTPROCESSING\n", " postprocessing"},
3441 {"#define USEREFLECTION\n", " reflection"},
3442 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3443 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3444 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3445 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3446 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3447 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3448 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3449 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
3450 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3451 {"#define USEALPHAKILL\n", " alphakill"},
3452 {"#define USEREFLECTCUBE\n", " reflectcube"},
3453 {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
3454 {"#define USEBOUNCEGRID\n", " bouncegrid"},
3457 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3458 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3460 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3461 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3462 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3463 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3464 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3465 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3466 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
3467 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3468 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3469 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3470 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3471 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3472 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3473 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3474 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3475 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3476 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDBOUNCELIGHT\n", " deferredbouncelight"},
3479 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
3481 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
3482 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3483 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3484 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3485 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3486 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3487 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
3488 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3489 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3490 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3491 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3492 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
3493 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
3494 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3495 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3496 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3497 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDBOUNCELIGHT\n", " deferredbouncelight"},
3500 struct r_glsl_permutation_s;
3501 typedef struct r_glsl_permutation_s
3503 /// hash lookup data
3504 struct r_glsl_permutation_s *hashnext;
3506 unsigned int permutation;
3508 /// indicates if we have tried compiling this permutation already
3510 /// 0 if compilation failed
3512 // texture units assigned to each detected uniform
3513 int tex_Texture_First;
3514 int tex_Texture_Second;
3515 int tex_Texture_GammaRamps;
3516 int tex_Texture_Normal;
3517 int tex_Texture_Color;
3518 int tex_Texture_Gloss;
3519 int tex_Texture_Glow;
3520 int tex_Texture_SecondaryNormal;
3521 int tex_Texture_SecondaryColor;
3522 int tex_Texture_SecondaryGloss;
3523 int tex_Texture_SecondaryGlow;
3524 int tex_Texture_Pants;
3525 int tex_Texture_Shirt;
3526 int tex_Texture_FogHeightTexture;
3527 int tex_Texture_FogMask;
3528 int tex_Texture_Lightmap;
3529 int tex_Texture_Deluxemap;
3530 int tex_Texture_Attenuation;
3531 int tex_Texture_Cube;
3532 int tex_Texture_Refraction;
3533 int tex_Texture_Reflection;
3534 int tex_Texture_ShadowMap2D;
3535 int tex_Texture_CubeProjection;
3536 int tex_Texture_ScreenDepth;
3537 int tex_Texture_ScreenNormalMap;
3538 int tex_Texture_ScreenDiffuse;
3539 int tex_Texture_ScreenSpecular;
3540 int tex_Texture_ReflectMask;
3541 int tex_Texture_ReflectCube;
3542 int tex_Texture_BounceGrid;
3543 /// locations of detected uniforms in program object, or -1 if not found
3544 int loc_Texture_First;
3545 int loc_Texture_Second;
3546 int loc_Texture_GammaRamps;
3547 int loc_Texture_Normal;
3548 int loc_Texture_Color;
3549 int loc_Texture_Gloss;
3550 int loc_Texture_Glow;
3551 int loc_Texture_SecondaryNormal;
3552 int loc_Texture_SecondaryColor;
3553 int loc_Texture_SecondaryGloss;
3554 int loc_Texture_SecondaryGlow;
3555 int loc_Texture_Pants;
3556 int loc_Texture_Shirt;
3557 int loc_Texture_FogHeightTexture;
3558 int loc_Texture_FogMask;
3559 int loc_Texture_Lightmap;
3560 int loc_Texture_Deluxemap;
3561 int loc_Texture_Attenuation;
3562 int loc_Texture_Cube;
3563 int loc_Texture_Refraction;
3564 int loc_Texture_Reflection;
3565 int loc_Texture_ShadowMap2D;
3566 int loc_Texture_CubeProjection;
3567 int loc_Texture_ScreenDepth;
3568 int loc_Texture_ScreenNormalMap;
3569 int loc_Texture_ScreenDiffuse;
3570 int loc_Texture_ScreenSpecular;
3571 int loc_Texture_ReflectMask;
3572 int loc_Texture_ReflectCube;
3573 int loc_Texture_BounceGrid;
3575 int loc_BloomBlur_Parameters;
3577 int loc_Color_Ambient;
3578 int loc_Color_Diffuse;
3579 int loc_Color_Specular;
3581 int loc_Color_Pants;
3582 int loc_Color_Shirt;
3583 int loc_DeferredColor_Ambient;
3584 int loc_DeferredColor_Diffuse;
3585 int loc_DeferredColor_Specular;
3586 int loc_DeferredMod_Diffuse;
3587 int loc_DeferredMod_Specular;
3588 int loc_DistortScaleRefractReflect;
3589 int loc_EyePosition;
3591 int loc_FogHeightFade;
3593 int loc_FogPlaneViewDist;
3594 int loc_FogRangeRecip;
3597 int loc_LightPosition;
3598 int loc_OffsetMapping_Scale;
3600 int loc_ReflectColor;
3601 int loc_ReflectFactor;
3602 int loc_ReflectOffset;
3603 int loc_RefractColor;
3605 int loc_ScreenCenterRefractReflect;
3606 int loc_ScreenScaleRefractReflect;
3607 int loc_ScreenToDepth;
3608 int loc_ShadowMap_Parameters;
3609 int loc_ShadowMap_TextureScale;
3610 int loc_SpecularPower;
3615 int loc_ViewTintColor;
3616 int loc_ViewToLight;
3617 int loc_ModelToLight;
3619 int loc_BackgroundTexMatrix;
3620 int loc_ModelViewProjectionMatrix;
3621 int loc_ModelViewMatrix;
3622 int loc_PixelToScreenTexCoord;
3623 int loc_ModelToReflectCube;
3624 int loc_ShadowMapMatrix;
3625 int loc_BloomColorSubtract;
3626 int loc_NormalmapScrollBlend;
3627 int loc_BounceGridMatrix;
3628 int loc_BounceGridIntensity;
3630 r_glsl_permutation_t;
3632 #define SHADERPERMUTATION_HASHSIZE 256
3635 // non-degradable "lightweight" shader parameters to keep the permutations simpler
3636 // these can NOT degrade! only use for simple stuff
3639 SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
3640 SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3641 SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
3642 SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
3643 SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
3644 SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5 ///< postprocess uservec4 is enabled
3646 #define SHADERSTATICPARMS_COUNT 6
3648 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
3649 static int shaderstaticparms_count = 0;
3651 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
3652 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
3653 qboolean R_CompileShader_CheckStaticParms(void)
3655 static int r_compileshader_staticparms_save[1];
3656 memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
3657 memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
3660 if (r_glsl_saturation_redcompensate.integer)
3661 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
3662 if (r_shadow_glossexact.integer)
3663 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
3664 if (r_glsl_postprocess.integer)
3666 if (r_glsl_postprocess_uservec1_enable.integer)
3667 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
3668 if (r_glsl_postprocess_uservec2_enable.integer)
3669 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
3670 if (r_glsl_postprocess_uservec3_enable.integer)
3671 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
3672 if (r_glsl_postprocess_uservec4_enable.integer)
3673 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
3675 return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
3678 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
3679 if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
3680 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
3682 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
3683 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
3685 shaderstaticparms_count = 0;
3688 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
3689 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
3690 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
3691 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
3692 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
3693 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
3696 /// information about each possible shader permutation
3697 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3698 /// currently selected permutation
3699 r_glsl_permutation_t *r_glsl_permutation;
3700 /// storage for permutations linked in the hash table
3701 memexpandablearray_t r_glsl_permutationarray;
3703 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3705 //unsigned int hashdepth = 0;
3706 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3707 r_glsl_permutation_t *p;
3708 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3710 if (p->mode == mode && p->permutation == permutation)
3712 //if (hashdepth > 10)
3713 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3718 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3720 p->permutation = permutation;
3721 p->hashnext = r_glsl_permutationhash[mode][hashindex];
3722 r_glsl_permutationhash[mode][hashindex] = p;
3723 //if (hashdepth > 10)
3724 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3728 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3731 if (!filename || !filename[0])
3733 if (!strcmp(filename, "glsl/default.glsl"))
3735 if (!glslshaderstring)
3737 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3738 if (glslshaderstring)
3739 Con_DPrintf("Loading shaders from file %s...\n", filename);
3741 glslshaderstring = (char *)builtinshaderstring;
3743 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3744 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3745 return shaderstring;
3747 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3750 if (printfromdisknotice)
3751 Con_DPrintf("from disk %s... ", filename);
3752 return shaderstring;
3754 return shaderstring;
3757 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3761 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3762 char *vertexstring, *geometrystring, *fragmentstring;
3763 char permutationname[256];
3764 int vertstrings_count = 0;
3765 int geomstrings_count = 0;
3766 int fragstrings_count = 0;
3767 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3768 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3769 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3776 permutationname[0] = 0;
3777 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
3778 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3779 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3781 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3783 // the first pretext is which type of shader to compile as
3784 // (later these will all be bound together as a program object)
3785 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3786 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3787 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3789 // the second pretext is the mode (for example a light source)
3790 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3791 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3792 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3793 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3795 // now add all the permutation pretexts
3796 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3798 if (permutation & (1<<i))
3800 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3801 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3802 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3803 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3807 // keep line numbers correct
3808 vertstrings_list[vertstrings_count++] = "\n";
3809 geomstrings_list[geomstrings_count++] = "\n";
3810 fragstrings_list[fragstrings_count++] = "\n";
3815 R_CompileShader_AddStaticParms(mode, permutation);
3816 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3817 vertstrings_count += shaderstaticparms_count;
3818 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3819 geomstrings_count += shaderstaticparms_count;
3820 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3821 fragstrings_count += shaderstaticparms_count;
3823 // now append the shader text itself
3824 vertstrings_list[vertstrings_count++] = vertexstring;
3825 geomstrings_list[geomstrings_count++] = geometrystring;
3826 fragstrings_list[fragstrings_count++] = fragmentstring;
3828 // if any sources were NULL, clear the respective list
3830 vertstrings_count = 0;
3831 if (!geometrystring)
3832 geomstrings_count = 0;
3833 if (!fragmentstring)
3834 fragstrings_count = 0;
3836 // compile the shader program
3837 if (vertstrings_count + geomstrings_count + fragstrings_count)
3838 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3842 qglUseProgram(p->program);CHECKGLERROR
3843 // look up all the uniform variable names we care about, so we don't
3844 // have to look them up every time we set them
3846 p->loc_Texture_First = qglGetUniformLocation(p->program, "Texture_First");
3847 p->loc_Texture_Second = qglGetUniformLocation(p->program, "Texture_Second");
3848 p->loc_Texture_GammaRamps = qglGetUniformLocation(p->program, "Texture_GammaRamps");
3849 p->loc_Texture_Normal = qglGetUniformLocation(p->program, "Texture_Normal");
3850 p->loc_Texture_Color = qglGetUniformLocation(p->program, "Texture_Color");
3851 p->loc_Texture_Gloss = qglGetUniformLocation(p->program, "Texture_Gloss");
3852 p->loc_Texture_Glow = qglGetUniformLocation(p->program, "Texture_Glow");
3853 p->loc_Texture_SecondaryNormal = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
3854 p->loc_Texture_SecondaryColor = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
3855 p->loc_Texture_SecondaryGloss = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
3856 p->loc_Texture_SecondaryGlow = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
3857 p->loc_Texture_Pants = qglGetUniformLocation(p->program, "Texture_Pants");
3858 p->loc_Texture_Shirt = qglGetUniformLocation(p->program, "Texture_Shirt");
3859 p->loc_Texture_FogHeightTexture = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
3860 p->loc_Texture_FogMask = qglGetUniformLocation(p->program, "Texture_FogMask");
3861 p->loc_Texture_Lightmap = qglGetUniformLocation(p->program, "Texture_Lightmap");
3862 p->loc_Texture_Deluxemap = qglGetUniformLocation(p->program, "Texture_Deluxemap");
3863 p->loc_Texture_Attenuation = qglGetUniformLocation(p->program, "Texture_Attenuation");
3864 p->loc_Texture_Cube = qglGetUniformLocation(p->program, "Texture_Cube");
3865 p->loc_Texture_Refraction = qglGetUniformLocation(p->program, "Texture_Refraction");
3866 p->loc_Texture_Reflection = qglGetUniformLocation(p->program, "Texture_Reflection");
3867 p->loc_Texture_ShadowMap2D = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
3868 p->loc_Texture_CubeProjection = qglGetUniformLocation(p->program, "Texture_CubeProjection");
3869 p->loc_Texture_ScreenDepth = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
3870 p->loc_Texture_ScreenNormalMap = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
3871 p->loc_Texture_ScreenDiffuse = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
3872 p->loc_Texture_ScreenSpecular = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
3873 p->loc_Texture_ReflectMask = qglGetUniformLocation(p->program, "Texture_ReflectMask");
3874 p->loc_Texture_ReflectCube = qglGetUniformLocation(p->program, "Texture_ReflectCube");
3875 p->loc_Texture_BounceGrid = qglGetUniformLocation(p->program, "Texture_BounceGrid");
3876 p->loc_Alpha = qglGetUniformLocation(p->program, "Alpha");
3877 p->loc_BloomBlur_Parameters = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
3878 p->loc_ClientTime = qglGetUniformLocation(p->program, "ClientTime");
3879 p->loc_Color_Ambient = qglGetUniformLocation(p->program, "Color_Ambient");
3880 p->loc_Color_Diffuse = qglGetUniformLocation(p->program, "Color_Diffuse");
3881 p->loc_Color_Specular = qglGetUniformLocation(p->program, "Color_Specular");
3882 p->loc_Color_Glow = qglGetUniformLocation(p->program, "Color_Glow");
3883 p->loc_Color_Pants = qglGetUniformLocation(p->program, "Color_Pants");
3884 p->loc_Color_Shirt = qglGetUniformLocation(p->program, "Color_Shirt");
3885 p->loc_DeferredColor_Ambient = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
3886 p->loc_DeferredColor_Diffuse = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
3887 p->loc_DeferredColor_Specular = qglGetUniformLocation(p->program, "DeferredColor_Specular");
3888 p->loc_DeferredMod_Diffuse = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
3889 p->loc_DeferredMod_Specular = qglGetUniformLocation(p->program, "DeferredMod_Specular");
3890 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
3891 p->loc_EyePosition = qglGetUniformLocation(p->program, "EyePosition");
3892 p->loc_FogColor = qglGetUniformLocation(p->program, "FogColor");
3893 p->loc_FogHeightFade = qglGetUniformLocation(p->program, "FogHeightFade");
3894 p->loc_FogPlane = qglGetUniformLocation(p->program, "FogPlane");
3895 p->loc_FogPlaneViewDist = qglGetUniformLocation(p->program, "FogPlaneViewDist");
3896 p->loc_FogRangeRecip = qglGetUniformLocation(p->program, "FogRangeRecip");
3897 p->loc_LightColor = qglGetUniformLocation(p->program, "LightColor");
3898 p->loc_LightDir = qglGetUniformLocation(p->program, "LightDir");
3899 p->loc_LightPosition = qglGetUniformLocation(p->program, "LightPosition");
3900 p->loc_OffsetMapping_Scale = qglGetUniformLocation(p->program, "OffsetMapping_Scale");
3901 p->loc_PixelSize = qglGetUniformLocation(p->program, "PixelSize");
3902 p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor");
3903 p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor");
3904 p->loc_ReflectOffset = qglGetUniformLocation(p->program, "ReflectOffset");
3905 p->loc_RefractColor = qglGetUniformLocation(p->program, "RefractColor");
3906 p->loc_Saturation = qglGetUniformLocation(p->program, "Saturation");
3907 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
3908 p->loc_ScreenScaleRefractReflect = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
3909 p->loc_ScreenToDepth = qglGetUniformLocation(p->program, "ScreenToDepth");
3910 p->loc_ShadowMap_Parameters = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
3911 p->loc_ShadowMap_TextureScale = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
3912 p->loc_SpecularPower = qglGetUniformLocation(p->program, "SpecularPower");
3913 p->loc_UserVec1 = qglGetUniformLocation(p->program, "UserVec1");
3914 p->loc_UserVec2 = qglGetUniformLocation(p->program, "UserVec2");
3915 p->loc_UserVec3 = qglGetUniformLocation(p->program, "UserVec3");
3916 p->loc_UserVec4 = qglGetUniformLocation(p->program, "UserVec4");
3917 p->loc_ViewTintColor = qglGetUniformLocation(p->program, "ViewTintColor");
3918 p->loc_ViewToLight = qglGetUniformLocation(p->program, "ViewToLight");
3919 p->loc_ModelToLight = qglGetUniformLocation(p->program, "ModelToLight");
3920 p->loc_TexMatrix = qglGetUniformLocation(p->program, "TexMatrix");
3921 p->loc_BackgroundTexMatrix = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
3922 p->loc_ModelViewMatrix = qglGetUniformLocation(p->program, "ModelViewMatrix");
3923 p->loc_ModelViewProjectionMatrix = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
3924 p->loc_PixelToScreenTexCoord = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
3925 p->loc_ModelToReflectCube = qglGetUniformLocation(p->program, "ModelToReflectCube");
3926 p->loc_ShadowMapMatrix = qglGetUniformLocation(p->program, "ShadowMapMatrix");
3927 p->loc_BloomColorSubtract = qglGetUniformLocation(p->program, "BloomColorSubtract");
3928 p->loc_NormalmapScrollBlend = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
3929 p->loc_BounceGridMatrix = qglGetUniformLocation(p->program, "BounceGridMatrix");
3930 p->loc_BounceGridIntensity = qglGetUniformLocation(p->program, "BounceGridIntensity");
3931 // initialize the samplers to refer to the texture units we use
3932 p->tex_Texture_First = -1;
3933 p->tex_Texture_Second = -1;
3934 p->tex_Texture_GammaRamps = -1;
3935 p->tex_Texture_Normal = -1;
3936 p->tex_Texture_Color = -1;
3937 p->tex_Texture_Gloss = -1;
3938 p->tex_Texture_Glow = -1;
3939 p->tex_Texture_SecondaryNormal = -1;
3940 p->tex_Texture_SecondaryColor = -1;
3941 p->tex_Texture_SecondaryGloss = -1;
3942 p->tex_Texture_SecondaryGlow = -1;
3943 p->tex_Texture_Pants = -1;
3944 p->tex_Texture_Shirt = -1;
3945 p->tex_Texture_FogHeightTexture = -1;
3946 p->tex_Texture_FogMask = -1;
3947 p->tex_Texture_Lightmap = -1;
3948 p->tex_Texture_Deluxemap = -1;
3949 p->tex_Texture_Attenuation = -1;
3950 p->tex_Texture_Cube = -1;
3951 p->tex_Texture_Refraction = -1;
3952 p->tex_Texture_Reflection = -1;
3953 p->tex_Texture_ShadowMap2D = -1;
3954 p->tex_Texture_CubeProjection = -1;
3955 p->tex_Texture_ScreenDepth = -1;
3956 p->tex_Texture_ScreenNormalMap = -1;
3957 p->tex_Texture_ScreenDiffuse = -1;
3958 p->tex_Texture_ScreenSpecular = -1;
3959 p->tex_Texture_ReflectMask = -1;
3960 p->tex_Texture_ReflectCube = -1;
3961 p->tex_Texture_BounceGrid = -1;
3963 if (p->loc_Texture_First >= 0) {p->tex_Texture_First = sampler;qglUniform1i(p->loc_Texture_First , sampler);sampler++;}
3964 if (p->loc_Texture_Second >= 0) {p->tex_Texture_Second = sampler;qglUniform1i(p->loc_Texture_Second , sampler);sampler++;}
3965 if (p->loc_Texture_GammaRamps >= 0) {p->tex_Texture_GammaRamps = sampler;qglUniform1i(p->loc_Texture_GammaRamps , sampler);sampler++;}
3966 if (p->loc_Texture_Normal >= 0) {p->tex_Texture_Normal = sampler;qglUniform1i(p->loc_Texture_Normal , sampler);sampler++;}
3967 if (p->loc_Texture_Color >= 0) {p->tex_Texture_Color = sampler;qglUniform1i(p->loc_Texture_Color , sampler);sampler++;}
3968 if (p->loc_Texture_Gloss >= 0) {p->tex_Texture_Gloss = sampler;qglUniform1i(p->loc_Texture_Gloss , sampler);sampler++;}
3969 if (p->loc_Texture_Glow >= 0) {p->tex_Texture_Glow = sampler;qglUniform1i(p->loc_Texture_Glow , sampler);sampler++;}
3970 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
3971 if (p->loc_Texture_SecondaryColor >= 0) {p->tex_Texture_SecondaryColor = sampler;qglUniform1i(p->loc_Texture_SecondaryColor , sampler);sampler++;}
3972 if (p->loc_Texture_SecondaryGloss >= 0) {p->tex_Texture_SecondaryGloss = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss , sampler);sampler++;}
3973 if (p->loc_Texture_SecondaryGlow >= 0) {p->tex_Texture_SecondaryGlow = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow , sampler);sampler++;}
3974 if (p->loc_Texture_Pants >= 0) {p->tex_Texture_Pants = sampler;qglUniform1i(p->loc_Texture_Pants , sampler);sampler++;}
3975 if (p->loc_Texture_Shirt >= 0) {p->tex_Texture_Shirt = sampler;qglUniform1i(p->loc_Texture_Shirt , sampler);sampler++;}
3976 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
3977 if (p->loc_Texture_FogMask >= 0) {p->tex_Texture_FogMask = sampler;qglUniform1i(p->loc_Texture_FogMask , sampler);sampler++;}
3978 if (p->loc_Texture_Lightmap >= 0) {p->tex_Texture_Lightmap = sampler;qglUniform1i(p->loc_Texture_Lightmap , sampler);sampler++;}
3979 if (p->loc_Texture_Deluxemap >= 0) {p->tex_Texture_Deluxemap = sampler;qglUniform1i(p->loc_Texture_Deluxemap , sampler);sampler++;}
3980 if (p->loc_Texture_Attenuation >= 0) {p->tex_Texture_Attenuation = sampler;qglUniform1i(p->loc_Texture_Attenuation , sampler);sampler++;}
3981 if (p->loc_Texture_Cube >= 0) {p->tex_Texture_Cube = sampler;qglUniform1i(p->loc_Texture_Cube , sampler);sampler++;}
3982 if (p->loc_Texture_Refraction >= 0) {p->tex_Texture_Refraction = sampler;qglUniform1i(p->loc_Texture_Refraction , sampler);sampler++;}
3983 if (p->loc_Texture_Reflection >= 0) {p->tex_Texture_Reflection = sampler;qglUniform1i(p->loc_Texture_Reflection , sampler);sampler++;}
3984 if (p->loc_Texture_ShadowMap2D >= 0) {p->tex_Texture_ShadowMap2D = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D , sampler);sampler++;}
3985 if (p->loc_Texture_CubeProjection >= 0) {p->tex_Texture_CubeProjection = sampler;qglUniform1i(p->loc_Texture_CubeProjection , sampler);sampler++;}
3986 if (p->loc_Texture_ScreenDepth >= 0) {p->tex_Texture_ScreenDepth = sampler;qglUniform1i(p->loc_Texture_ScreenDepth , sampler);sampler++;}
3987 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
3988 if (p->loc_Texture_ScreenDiffuse >= 0) {p->tex_Texture_ScreenDiffuse = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse , sampler);sampler++;}
3989 if (p->loc_Texture_ScreenSpecular >= 0) {p->tex_Texture_ScreenSpecular = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular , sampler);sampler++;}
3990 if (p->loc_Texture_ReflectMask >= 0) {p->tex_Texture_ReflectMask = sampler;qglUniform1i(p->loc_Texture_ReflectMask , sampler);sampler++;}
3991 if (p->loc_Texture_ReflectCube >= 0) {p->tex_Texture_ReflectCube = sampler;qglUniform1i(p->loc_Texture_ReflectCube , sampler);sampler++;}
3992 if (p->loc_Texture_BounceGrid >= 0) {p->tex_Texture_BounceGrid = sampler;qglUniform1i(p->loc_Texture_BounceGrid , sampler);sampler++;}
3994 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
3997 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
4001 Mem_Free(vertexstring);
4003 Mem_Free(geometrystring);
4005 Mem_Free(fragmentstring);
4008 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
4010 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
4011 if (r_glsl_permutation != perm)
4013 r_glsl_permutation = perm;
4014 if (!r_glsl_permutation->program)
4016 if (!r_glsl_permutation->compiled)
4017 R_GLSL_CompilePermutation(perm, mode, permutation);
4018 if (!r_glsl_permutation->program)
4020 // remove features until we find a valid permutation
4022 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4024 // reduce i more quickly whenever it would not remove any bits
4025 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4026 if (!(permutation & j))
4029 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
4030 if (!r_glsl_permutation->compiled)
4031 R_GLSL_CompilePermutation(perm, mode, permutation);
4032 if (r_glsl_permutation->program)
4035 if (i >= SHADERPERMUTATION_COUNT)
4037 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4038 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
4039 qglUseProgram(0);CHECKGLERROR
4040 return; // no bit left to clear, entire mode is broken
4045 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
4047 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
4048 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
4049 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
4056 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
4057 extern D3DCAPS9 vid_d3d9caps;
4060 struct r_hlsl_permutation_s;
4061 typedef struct r_hlsl_permutation_s
4063 /// hash lookup data
4064 struct r_hlsl_permutation_s *hashnext;
4066 unsigned int permutation;
4068 /// indicates if we have tried compiling this permutation already
4070 /// NULL if compilation failed
4071 IDirect3DVertexShader9 *vertexshader;
4072 IDirect3DPixelShader9 *pixelshader;
4074 r_hlsl_permutation_t;
4076 typedef enum D3DVSREGISTER_e
4078 D3DVSREGISTER_TexMatrix = 0, // float4x4
4079 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
4080 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
4081 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
4082 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
4083 D3DVSREGISTER_ModelToLight = 20, // float4x4
4084 D3DVSREGISTER_EyePosition = 24,
4085 D3DVSREGISTER_FogPlane = 25,
4086 D3DVSREGISTER_LightDir = 26,
4087 D3DVSREGISTER_LightPosition = 27,
4091 typedef enum D3DPSREGISTER_e
4093 D3DPSREGISTER_Alpha = 0,
4094 D3DPSREGISTER_BloomBlur_Parameters = 1,
4095 D3DPSREGISTER_ClientTime = 2,
4096 D3DPSREGISTER_Color_Ambient = 3,
4097 D3DPSREGISTER_Color_Diffuse = 4,
4098 D3DPSREGISTER_Color_Specular = 5,
4099 D3DPSREGISTER_Color_Glow = 6,
4100 D3DPSREGISTER_Color_Pants = 7,
4101 D3DPSREGISTER_Color_Shirt = 8,
4102 D3DPSREGISTER_DeferredColor_Ambient = 9,
4103 D3DPSREGISTER_DeferredColor_Diffuse = 10,
4104 D3DPSREGISTER_DeferredColor_Specular = 11,
4105 D3DPSREGISTER_DeferredMod_Diffuse = 12,
4106 D3DPSREGISTER_DeferredMod_Specular = 13,
4107 D3DPSREGISTER_DistortScaleRefractReflect = 14,
4108 D3DPSREGISTER_EyePosition = 15, // unused
4109 D3DPSREGISTER_FogColor = 16,
4110 D3DPSREGISTER_FogHeightFade = 17,
4111 D3DPSREGISTER_FogPlane = 18,
4112 D3DPSREGISTER_FogPlaneViewDist = 19,
4113 D3DPSREGISTER_FogRangeRecip = 20,
4114 D3DPSREGISTER_LightColor = 21,
4115 D3DPSREGISTER_LightDir = 22, // unused
4116 D3DPSREGISTER_LightPosition = 23,
4117 D3DPSREGISTER_OffsetMapping_Scale = 24,
4118 D3DPSREGISTER_PixelSize = 25,
4119 D3DPSREGISTER_ReflectColor = 26,
4120 D3DPSREGISTER_ReflectFactor = 27,
4121 D3DPSREGISTER_ReflectOffset = 28,
4122 D3DPSREGISTER_RefractColor = 29,
4123 D3DPSREGISTER_Saturation = 30,
4124 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
4125 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
4126 D3DPSREGISTER_ScreenToDepth = 33,
4127 D3DPSREGISTER_ShadowMap_Parameters = 34,
4128 D3DPSREGISTER_ShadowMap_TextureScale = 35,
4129 D3DPSREGISTER_SpecularPower = 36,
4130 D3DPSREGISTER_UserVec1 = 37,
4131 D3DPSREGISTER_UserVec2 = 38,
4132 D3DPSREGISTER_UserVec3 = 39,
4133 D3DPSREGISTER_UserVec4 = 40,
4134 D3DPSREGISTER_ViewTintColor = 41,
4135 D3DPSREGISTER_PixelToScreenTexCoord = 42,
4136 D3DPSREGISTER_BloomColorSubtract = 43,
4137 D3DPSREGISTER_ViewToLight = 44, // float4x4
4138 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
4139 D3DPSREGISTER_NormalmapScrollBlend = 52,
4144 /// information about each possible shader permutation
4145 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4146 /// currently selected permutation
4147 r_hlsl_permutation_t *r_hlsl_permutation;
4148 /// storage for permutations linked in the hash table
4149 memexpandablearray_t r_hlsl_permutationarray;
4151 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
4153 //unsigned int hashdepth = 0;
4154 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4155 r_hlsl_permutation_t *p;
4156 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
4158 if (p->mode == mode && p->permutation == permutation)
4160 //if (hashdepth > 10)
4161 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4166 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
4168 p->permutation = permutation;
4169 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
4170 r_hlsl_permutationhash[mode][hashindex] = p;
4171 //if (hashdepth > 10)
4172 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4176 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
4179 if (!filename || !filename[0])
4181 if (!strcmp(filename, "hlsl/default.hlsl"))
4183 if (!hlslshaderstring)
4185 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4186 if (hlslshaderstring)
4187 Con_DPrintf("Loading shaders from file %s...\n", filename);
4189 hlslshaderstring = (char *)builtinhlslshaderstring;
4191 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
4192 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
4193 return shaderstring;
4195 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4198 if (printfromdisknotice)
4199 Con_DPrintf("from disk %s... ", filename);
4200 return shaderstring;
4202 return shaderstring;
4206 //#include <d3dx9shader.h>
4207 //#include <d3dx9mesh.h>
4209 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4211 DWORD *vsbin = NULL;
4212 DWORD *psbin = NULL;
4213 fs_offset_t vsbinsize;
4214 fs_offset_t psbinsize;
4215 // IDirect3DVertexShader9 *vs = NULL;
4216 // IDirect3DPixelShader9 *ps = NULL;
4217 ID3DXBuffer *vslog = NULL;
4218 ID3DXBuffer *vsbuffer = NULL;
4219 ID3DXConstantTable *vsconstanttable = NULL;
4220 ID3DXBuffer *pslog = NULL;
4221 ID3DXBuffer *psbuffer = NULL;
4222 ID3DXConstantTable *psconstanttable = NULL;
4225 char temp[MAX_INPUTLINE];
4226 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
4227 qboolean debugshader = gl_paranoid.integer != 0;
4228 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4229 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4232 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
4233 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
4235 if ((!vsbin && vertstring) || (!psbin && fragstring))
4237 const char* dllnames_d3dx9 [] =
4261 dllhandle_t d3dx9_dll = NULL;
4262 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4263 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
4264 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4265 dllfunction_t d3dx9_dllfuncs[] =
4267 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
4268 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
4269 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
4272 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
4274 DWORD shaderflags = 0;
4276 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
4277 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4278 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4279 if (vertstring && vertstring[0])
4283 // vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
4284 // FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
4285 FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
4286 vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4289 vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4292 vsbinsize = vsbuffer->GetBufferSize();
4293 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
4294 memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
4295 vsbuffer->Release();
4299 strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
4300 Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
4304 if (fragstring && fragstring[0])
4308 // psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
4309 // FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
4310 FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
4311 psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4314 psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4317 psbinsize = psbuffer->GetBufferSize();
4318 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
4319 memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
4320 psbuffer->Release();
4324 strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
4325 Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
4329 Sys_UnloadLibrary(&d3dx9_dll);
4332 Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
4336 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
4337 if (FAILED(vsresult))
4338 Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
4339 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
4340 if (FAILED(psresult))
4341 Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
4343 // free the shader data
4344 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4345 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4348 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
4351 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
4352 int vertstring_length = 0;
4353 int geomstring_length = 0;
4354 int fragstring_length = 0;
4356 char *vertexstring, *geometrystring, *fragmentstring;
4357 char *vertstring, *geomstring, *fragstring;
4358 char permutationname[256];
4359 char cachename[256];
4360 int vertstrings_count = 0;
4361 int geomstrings_count = 0;
4362 int fragstrings_count = 0;
4363 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4364 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4365 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4370 p->vertexshader = NULL;
4371 p->pixelshader = NULL;
4373 permutationname[0] = 0;
4375 vertexstring = R_HLSL_GetText(modeinfo->vertexfilename, true);
4376 geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
4377 fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
4379 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4380 strlcat(cachename, "hlsl/", sizeof(cachename));
4382 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
4383 vertstrings_count = 0;
4384 geomstrings_count = 0;
4385 fragstrings_count = 0;
4386 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
4387 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
4388 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
4390 // the first pretext is which type of shader to compile as
4391 // (later these will all be bound together as a program object)
4392 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4393 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4394 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4396 // the second pretext is the mode (for example a light source)
4397 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4398 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4399 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4400 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4401 strlcat(cachename, modeinfo->name, sizeof(cachename));
4403 // now add all the permutation pretexts
4404 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4406 if (permutation & (1<<i))
4408 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4409 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4410 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4411 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4412 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4416 // keep line numbers correct
4417 vertstrings_list[vertstrings_count++] = "\n";
4418 geomstrings_list[geomstrings_count++] = "\n";
4419 fragstrings_list[fragstrings_count++] = "\n";
4424 R_CompileShader_AddStaticParms(mode, permutation);
4425 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4426 vertstrings_count += shaderstaticparms_count;
4427 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4428 geomstrings_count += shaderstaticparms_count;
4429 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4430 fragstrings_count += shaderstaticparms_count;
4432 // replace spaces in the cachename with _ characters
4433 for (i = 0;cachename[i];i++)
4434 if (cachename[i] == ' ')
4437 // now append the shader text itself
4438 vertstrings_list[vertstrings_count++] = vertexstring;
4439 geomstrings_list[geomstrings_count++] = geometrystring;
4440 fragstrings_list[fragstrings_count++] = fragmentstring;
4442 // if any sources were NULL, clear the respective list
4444 vertstrings_count = 0;
4445 if (!geometrystring)
4446 geomstrings_count = 0;
4447 if (!fragmentstring)
4448 fragstrings_count = 0;
4450 vertstring_length = 0;
4451 for (i = 0;i < vertstrings_count;i++)
4452 vertstring_length += strlen(vertstrings_list[i]);
4453 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
4454 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4455 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4457 geomstring_length = 0;
4458 for (i = 0;i < geomstrings_count;i++)
4459 geomstring_length += strlen(geomstrings_list[i]);
4460 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
4461 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4462 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4464 fragstring_length = 0;
4465 for (i = 0;i < fragstrings_count;i++)
4466 fragstring_length += strlen(fragstrings_list[i]);
4467 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
4468 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4469 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4471 // try to load the cached shader, or generate one
4472 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
4474 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
4475 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
4477 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
4481 Mem_Free(vertstring);
4483 Mem_Free(geomstring);
4485 Mem_Free(fragstring);
4487 Mem_Free(vertexstring);
4489 Mem_Free(geometrystring);
4491 Mem_Free(fragmentstring);
4494 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
4495 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
4496 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);}
4497 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);}
4498 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);}
4499 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);}
4501 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
4502 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
4503 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);}
4504 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);}
4505 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);}
4506 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);}
4508 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
4510 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
4511 if (r_hlsl_permutation != perm)
4513 r_hlsl_permutation = perm;
4514 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4516 if (!r_hlsl_permutation->compiled)
4517 R_HLSL_CompilePermutation(perm, mode, permutation);
4518 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4520 // remove features until we find a valid permutation
4522 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4524 // reduce i more quickly whenever it would not remove any bits
4525 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4526 if (!(permutation & j))
4529 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4530 if (!r_hlsl_permutation->compiled)
4531 R_HLSL_CompilePermutation(perm, mode, permutation);
4532 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
4535 if (i >= SHADERPERMUTATION_COUNT)
4537 //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4538 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4539 return; // no bit left to clear, entire mode is broken
4543 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
4544 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
4546 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
4547 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
4548 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
4552 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
4554 DPSOFTRAST_SetShader(mode, permutation);
4555 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
4556 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
4557 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
4560 void R_GLSL_Restart_f(void)
4562 unsigned int i, limit;
4563 if (glslshaderstring && glslshaderstring != builtinshaderstring)
4564 Mem_Free(glslshaderstring);
4565 glslshaderstring = NULL;
4566 if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
4567 Mem_Free(hlslshaderstring);
4568 hlslshaderstring = NULL;
4569 switch(vid.renderpath)
4571 case RENDERPATH_D3D9:
4574 r_hlsl_permutation_t *p;
4575 r_hlsl_permutation = NULL;
4576 limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
4577 for (i = 0;i < limit;i++)
4579 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
4581 if (p->vertexshader)
4582 IDirect3DVertexShader9_Release(p->vertexshader);
4584 IDirect3DPixelShader9_Release(p->pixelshader);
4585 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
4588 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4592 case RENDERPATH_D3D10:
4593 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4595 case RENDERPATH_D3D11:
4596 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4598 case RENDERPATH_GL20:
4599 case RENDERPATH_GLES2:
4601 r_glsl_permutation_t *p;
4602 r_glsl_permutation = NULL;
4603 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
4604 for (i = 0;i < limit;i++)
4606 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
4608 GL_Backend_FreeProgram(p->program);
4609 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
4612 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4615 case RENDERPATH_GL13:
4616 case RENDERPATH_GL11:
4618 case RENDERPATH_SOFT:
4623 void R_GLSL_DumpShader_f(void)
4628 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
4631 FS_Print(file, "/* The engine may define the following macros:\n");
4632 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4633 for (i = 0;i < SHADERMODE_COUNT;i++)
4634 FS_Print(file, glslshadermodeinfo[i].pretext);
4635 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4636 FS_Print(file, shaderpermutationinfo[i].pretext);
4637 FS_Print(file, "*/\n");
4638 FS_Print(file, builtinshaderstring);
4640 Con_Printf("glsl/default.glsl written\n");
4643 Con_Printf("failed to write to glsl/default.glsl\n");
4645 file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
4648 FS_Print(file, "/* The engine may define the following macros:\n");
4649 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4650 for (i = 0;i < SHADERMODE_COUNT;i++)
4651 FS_Print(file, hlslshadermodeinfo[i].pretext);
4652 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4653 FS_Print(file, shaderpermutationinfo[i].pretext);
4654 FS_Print(file, "*/\n");
4655 FS_Print(file, builtinhlslshaderstring);
4657 Con_Printf("hlsl/default.hlsl written\n");
4660 Con_Printf("failed to write to hlsl/default.hlsl\n");
4663 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
4666 texturemode = GL_MODULATE;
4667 switch (vid.renderpath)
4669 case RENDERPATH_D3D9:
4671 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))));
4672 R_Mesh_TexBind(GL20TU_FIRST , first );
4673 R_Mesh_TexBind(GL20TU_SECOND, second);
4676 case RENDERPATH_D3D10:
4677 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4679 case RENDERPATH_D3D11:
4680 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4682 case RENDERPATH_GL20:
4683 case RENDERPATH_GLES2:
4684 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))));
4685 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
4686 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
4688 case RENDERPATH_GL13:
4689 R_Mesh_TexBind(0, first );
4690 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
4691 R_Mesh_TexBind(1, second);
4693 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
4695 case RENDERPATH_GL11:
4696 R_Mesh_TexBind(0, first );
4698 case RENDERPATH_SOFT:
4699 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))));
4700 R_Mesh_TexBind(GL20TU_FIRST , first );
4701 R_Mesh_TexBind(GL20TU_SECOND, second);
4706 void R_SetupShader_DepthOrShadow(void)
4708 switch (vid.renderpath)
4710 case RENDERPATH_D3D9:
4712 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4715 case RENDERPATH_D3D10:
4716 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4718 case RENDERPATH_D3D11:
4719 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4721 case RENDERPATH_GL20:
4722 case RENDERPATH_GLES2:
4723 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4725 case RENDERPATH_GL13:
4726 R_Mesh_TexBind(0, 0);
4727 R_Mesh_TexBind(1, 0);
4729 case RENDERPATH_GL11:
4730 R_Mesh_TexBind(0, 0);
4732 case RENDERPATH_SOFT:
4733 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
4738 void R_SetupShader_ShowDepth(void)
4740 switch (vid.renderpath)
4742 case RENDERPATH_D3D9:
4744 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
4747 case RENDERPATH_D3D10:
4748 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4750 case RENDERPATH_D3D11:
4751 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4753 case RENDERPATH_GL20:
4754 case RENDERPATH_GLES2:
4755 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
4757 case RENDERPATH_GL13:
4759 case RENDERPATH_GL11:
4761 case RENDERPATH_SOFT:
4762 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
4767 extern qboolean r_shadow_usingdeferredprepass;
4768 extern cvar_t r_shadow_deferred_8bitrange;
4769 extern rtexture_t *r_shadow_attenuationgradienttexture;
4770 extern rtexture_t *r_shadow_attenuation2dtexture;
4771 extern rtexture_t *r_shadow_attenuation3dtexture;
4772 extern qboolean r_shadow_usingshadowmap2d;
4773 extern qboolean r_shadow_usingshadowmaportho;
4774 extern float r_shadow_shadowmap_texturescale[2];
4775 extern float r_shadow_shadowmap_parameters[4];
4776 extern qboolean r_shadow_shadowmapvsdct;
4777 extern qboolean r_shadow_shadowmapsampler;
4778 extern int r_shadow_shadowmappcf;
4779 extern rtexture_t *r_shadow_shadowmap2dtexture;
4780 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
4781 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
4782 extern matrix4x4_t r_shadow_shadowmapmatrix;
4783 extern int r_shadow_shadowmaplod; // changes for each light based on distance
4784 extern int r_shadow_prepass_width;
4785 extern int r_shadow_prepass_height;
4786 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
4787 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
4788 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
4789 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
4790 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
4791 static qboolean R_BlendFuncAllowsColormod(int src, int dst)
4793 // a blendfunc allows colormod if:
4794 // a) it can never keep the destination pixel invariant, or
4795 // b) it can keep the destination pixel invariant, and still can do so if colormodded
4796 // this is to prevent unintended side effects from colormod
4799 // IF there is a (s, sa) for which for all (d, da),
4800 // s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
4801 // THEN, for this (s, sa) and all (colormod, d, da):
4802 // s*colormod * src(s*colormod, d, sa, da) + d * dst(s*colormod, d, sa, da) == d
4803 // OBVIOUSLY, this means that
4804 // s*colormod * src(s*colormod, d, sa, da) = 0
4805 // dst(s*colormod, d, sa, da) = 1
4807 // note: not caring about GL_SRC_ALPHA_SATURATE and following here, these are unused in DP code
4809 // main condition to leave dst color invariant:
4810 // s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
4812 // s * 0 + d * dst(s, d, sa, da) == d
4813 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4814 // => colormod is a problem for GL_SRC_COLOR only
4816 // s + d * dst(s, d, sa, da) == d
4818 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4819 // => colormod is never problematic for these
4820 // src == GL_SRC_COLOR:
4821 // s*s + d * dst(s, d, sa, da) == d
4823 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4824 // => colormod is never problematic for these
4825 // src == GL_ONE_MINUS_SRC_COLOR:
4826 // s*(1-s) + d * dst(s, d, sa, da) == d
4827 // => s == 0 or s == 1
4828 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4829 // => colormod is a problem for GL_SRC_COLOR only
4830 // src == GL_DST_COLOR
4831 // s*d + d * dst(s, d, sa, da) == d
4833 // => dst == GL_ZERO/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4834 // => colormod is always a problem
4837 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4838 // => colormod is never problematic for these
4839 // => BUT, we do not know s! We must assume it is problematic
4840 // then... except in GL_ONE case, where we know all invariant
4842 // src == GL_ONE_MINUS_DST_COLOR
4843 // s*(1-d) + d * dst(s, d, sa, da) == d
4844 // => s == 0 (1-d is impossible to handle for our desired result)
4845 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4846 // => colormod is never problematic for these
4847 // src == GL_SRC_ALPHA
4848 // s*sa + d * dst(s, d, sa, da) == d
4849 // => s == 0, or sa == 0
4850 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4851 // => colormod breaks in the case GL_SRC_COLOR only
4852 // src == GL_ONE_MINUS_SRC_ALPHA
4853 // s*(1-sa) + d * dst(s, d, sa, da) == d
4854 // => s == 0, or sa == 1
4855 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4856 // => colormod breaks in the case GL_SRC_COLOR only
4857 // src == GL_DST_ALPHA
4858 // s*da + d * dst(s, d, sa, da) == d
4860 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4861 // => colormod is never problematic for these
4866 case GL_ONE_MINUS_SRC_COLOR:
4868 case GL_ONE_MINUS_SRC_ALPHA:
4869 if(dst == GL_SRC_COLOR)
4874 case GL_ONE_MINUS_DST_COLOR:
4876 case GL_ONE_MINUS_DST_ALPHA:
4886 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)
4888 // select a permutation of the lighting shader appropriate to this
4889 // combination of texture, entity, light source, and fogging, only use the
4890 // minimum features necessary to avoid wasting rendering time in the
4891 // fragment shader on features that are not being used
4892 unsigned int permutation = 0;
4893 unsigned int mode = 0;
4894 qboolean allow_colormod;
4895 static float dummy_colormod[3] = {1, 1, 1};
4896 float *colormod = rsurface.colormod;
4898 matrix4x4_t tempmatrix;
4899 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
4900 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4901 permutation |= SHADERPERMUTATION_ALPHAKILL;
4902 if (rsurfacepass == RSURFPASS_BACKGROUND)
4904 // distorted background
4905 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
4907 mode = SHADERMODE_WATER;
4908 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
4909 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND;
4910 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
4912 // this is the right thing to do for wateralpha
4913 GL_BlendFunc(GL_ONE, GL_ZERO);
4914 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
4918 // this is the right thing to do for entity alpha
4919 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4920 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4923 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
4925 mode = SHADERMODE_REFRACTION;
4926 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4927 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4931 mode = SHADERMODE_GENERIC;
4932 permutation |= SHADERPERMUTATION_DIFFUSE;
4933 GL_BlendFunc(GL_ONE, GL_ZERO);
4934 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
4937 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
4939 if (r_glsl_offsetmapping.integer)
4941 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4942 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4943 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4944 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4945 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4947 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4948 if (r_glsl_offsetmapping_reliefmapping.integer)
4949 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4952 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4953 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4954 // normalmap (deferred prepass), may use alpha test on diffuse
4955 mode = SHADERMODE_DEFERREDGEOMETRY;
4956 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4957 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4958 GL_BlendFunc(GL_ONE, GL_ZERO);
4959 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
4961 else if (rsurfacepass == RSURFPASS_RTLIGHT)
4963 if (r_glsl_offsetmapping.integer)
4965 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4966 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4967 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4968 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4969 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4971 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4972 if (r_glsl_offsetmapping_reliefmapping.integer)
4973 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4976 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4977 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4979 mode = SHADERMODE_LIGHTSOURCE;
4980 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4981 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4982 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
4983 permutation |= SHADERPERMUTATION_CUBEFILTER;
4984 if (diffusescale > 0)
4985 permutation |= SHADERPERMUTATION_DIFFUSE;
4986 if (specularscale > 0)
4987 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4988 if (r_refdef.fogenabled)
4989 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
4990 if (rsurface.texture->colormapping)
4991 permutation |= SHADERPERMUTATION_COLORMAPPING;
4992 if (r_shadow_usingshadowmap2d)
4994 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4995 if(r_shadow_shadowmapvsdct)
4996 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4998 if (r_shadow_shadowmapsampler)
4999 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5000 if (r_shadow_shadowmappcf > 1)
5001 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5002 else if (r_shadow_shadowmappcf)
5003 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5005 if (rsurface.texture->reflectmasktexture)
5006 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5007 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5008 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE);
5010 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5012 if (r_glsl_offsetmapping.integer)
5014 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5015 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5016 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5017 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5018 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5020 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5021 if (r_glsl_offsetmapping_reliefmapping.integer)
5022 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5025 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5026 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5027 // unshaded geometry (fullbright or ambient model lighting)
5028 mode = SHADERMODE_FLATCOLOR;
5029 ambientscale = diffusescale = specularscale = 0;
5030 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5031 permutation |= SHADERPERMUTATION_GLOW;
5032 if (r_refdef.fogenabled)
5033 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5034 if (rsurface.texture->colormapping)
5035 permutation |= SHADERPERMUTATION_COLORMAPPING;
5036 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5038 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5039 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5041 if (r_shadow_shadowmapsampler)
5042 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5043 if (r_shadow_shadowmappcf > 1)
5044 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5045 else if (r_shadow_shadowmappcf)
5046 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5048 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5049 permutation |= SHADERPERMUTATION_REFLECTION;
5050 if (rsurface.texture->reflectmasktexture)
5051 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5052 if (r_shadow_bouncegridtexture)
5053 permutation |= SHADERPERMUTATION_BOUNCEGRID;
5054 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5055 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5057 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
5059 if (r_glsl_offsetmapping.integer)
5061 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5062 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5063 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5064 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5065 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5067 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5068 if (r_glsl_offsetmapping_reliefmapping.integer)
5069 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5072 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5073 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5074 // directional model lighting
5075 mode = SHADERMODE_LIGHTDIRECTION;
5076 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5077 permutation |= SHADERPERMUTATION_GLOW;
5078 permutation |= SHADERPERMUTATION_DIFFUSE;
5079 if (specularscale > 0)
5080 permutation |= SHADERPERMUTATION_SPECULAR;
5081 if (r_refdef.fogenabled)
5082 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5083 if (rsurface.texture->colormapping)
5084 permutation |= SHADERPERMUTATION_COLORMAPPING;
5085 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5087 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5088 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5090 if (r_shadow_shadowmapsampler)
5091 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5092 if (r_shadow_shadowmappcf > 1)
5093 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5094 else if (r_shadow_shadowmappcf)
5095 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5097 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5098 permutation |= SHADERPERMUTATION_REFLECTION;
5099 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5100 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5101 if (rsurface.texture->reflectmasktexture)
5102 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5103 if (r_shadow_bouncegridtexture)
5104 permutation |= SHADERPERMUTATION_BOUNCEGRID;
5105 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5106 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5108 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5110 if (r_glsl_offsetmapping.integer)
5112 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5113 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5114 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5115 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5116 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5118 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5119 if (r_glsl_offsetmapping_reliefmapping.integer)
5120 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5123 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5124 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5125 // ambient model lighting
5126 mode = SHADERMODE_LIGHTDIRECTION;
5127 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5128 permutation |= SHADERPERMUTATION_GLOW;
5129 if (r_refdef.fogenabled)
5130 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5131 if (rsurface.texture->colormapping)
5132 permutation |= SHADERPERMUTATION_COLORMAPPING;
5133 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5135 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5136 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5138 if (r_shadow_shadowmapsampler)
5139 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5140 if (r_shadow_shadowmappcf > 1)
5141 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5142 else if (r_shadow_shadowmappcf)
5143 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5145 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5146 permutation |= SHADERPERMUTATION_REFLECTION;
5147 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5148 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5149 if (rsurface.texture->reflectmasktexture)
5150 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5151 if (r_shadow_bouncegridtexture)
5152 permutation |= SHADERPERMUTATION_BOUNCEGRID;
5153 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5154 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5158 if (r_glsl_offsetmapping.integer)
5160 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5161 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5162 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5163 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5164 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5166 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5167 if (r_glsl_offsetmapping_reliefmapping.integer)
5168 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5171 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5172 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5174 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5175 permutation |= SHADERPERMUTATION_GLOW;
5176 if (r_refdef.fogenabled)
5177 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5178 if (rsurface.texture->colormapping)
5179 permutation |= SHADERPERMUTATION_COLORMAPPING;
5180 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5182 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5183 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5185 if (r_shadow_shadowmapsampler)
5186 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5187 if (r_shadow_shadowmappcf > 1)
5188 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5189 else if (r_shadow_shadowmappcf)
5190 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5192 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5193 permutation |= SHADERPERMUTATION_REFLECTION;
5194 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5195 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5196 if (rsurface.texture->reflectmasktexture)
5197 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5198 if (FAKELIGHT_ENABLED)
5200 // fake lightmapping (q1bsp, q3bsp, fullbright map)
5201 mode = SHADERMODE_FAKELIGHT;
5202 permutation |= SHADERPERMUTATION_DIFFUSE;
5203 if (specularscale > 0)
5204 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5206 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
5208 // deluxemapping (light direction texture)
5209 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
5210 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
5212 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5213 permutation |= SHADERPERMUTATION_DIFFUSE;
5214 if (specularscale > 0)
5215 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5217 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
5219 // fake deluxemapping (uniform light direction in tangentspace)
5220 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5221 permutation |= SHADERPERMUTATION_DIFFUSE;
5222 if (specularscale > 0)
5223 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5225 else if (rsurface.uselightmaptexture)
5227 // ordinary lightmapping (q1bsp, q3bsp)
5228 mode = SHADERMODE_LIGHTMAP;
5232 // ordinary vertex coloring (q3bsp)
5233 mode = SHADERMODE_VERTEXCOLOR;
5235 if (r_shadow_bouncegridtexture)
5236 permutation |= SHADERPERMUTATION_BOUNCEGRID;
5237 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5238 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5241 colormod = dummy_colormod;
5242 switch(vid.renderpath)
5244 case RENDERPATH_D3D9:
5246 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);
5247 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5248 R_SetupShader_SetPermutationHLSL(mode, permutation);
5249 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
5250 if (mode == SHADERMODE_LIGHTSOURCE)
5252 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
5253 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5257 if (mode == SHADERMODE_LIGHTDIRECTION)
5259 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5262 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
5263 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
5264 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
5265 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5266 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5268 if (mode == SHADERMODE_LIGHTSOURCE)
5270 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5271 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5272 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5273 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5274 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5276 // additive passes are only darkened by fog, not tinted
5277 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5278 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5282 if (mode == SHADERMODE_FLATCOLOR)
5284 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5286 else if (mode == SHADERMODE_LIGHTDIRECTION)
5288 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]);
5289 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5290 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);
5291 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);
5292 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5293 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
5294 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5298 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5299 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5300 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);
5301 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);
5302 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5304 // additive passes are only darkened by fog, not tinted
5305 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5306 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5308 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5309 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);
5310 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5311 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5312 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5313 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5314 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5315 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
5316 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5317 if (mode == SHADERMODE_WATER)
5318 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
5320 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5321 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5322 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5323 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));
5324 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5325 if (rsurface.texture->pantstexture)
5326 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5328 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
5329 if (rsurface.texture->shirttexture)
5330 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5332 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
5333 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5334 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
5335 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
5336 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
5337 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
5338 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5339 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5341 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
5342 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
5343 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
5344 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
5345 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
5346 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
5347 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
5348 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
5349 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
5350 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
5351 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
5352 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5353 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
5354 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
5355 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5356 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5357 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
5358 if (rsurfacepass == RSURFPASS_BACKGROUND)
5360 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5361 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5362 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5366 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5368 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
5369 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
5370 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
5371 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
5372 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5374 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
5375 if (rsurface.rtlight)
5377 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
5378 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
5383 case RENDERPATH_D3D10:
5384 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5386 case RENDERPATH_D3D11:
5387 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5389 case RENDERPATH_GL20:
5390 case RENDERPATH_GLES2:
5391 if (!vid.useinterleavedarrays)
5393 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);
5394 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5395 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5396 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5397 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5398 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5399 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5400 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5404 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);
5405 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5407 R_SetupShader_SetPermutationGLSL(mode, permutation);
5408 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
5409 if (mode == SHADERMODE_LIGHTSOURCE)
5411 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
5412 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5413 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5414 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5415 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5416 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);
5418 // additive passes are only darkened by fog, not tinted
5419 if (r_glsl_permutation->loc_FogColor >= 0)
5420 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5421 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5425 if (mode == SHADERMODE_FLATCOLOR)
5427 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5429 else if (mode == SHADERMODE_LIGHTDIRECTION)
5431 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]);
5432 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]);
5433 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);
5434 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);
5435 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);
5436 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]);
5437 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]);
5441 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]);
5442 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]);
5443 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);
5444 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);
5445 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);
5447 // additive passes are only darkened by fog, not tinted
5448 if (r_glsl_permutation->loc_FogColor >= 0)
5450 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5451 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5453 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5455 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);
5456 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]);
5457 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]);
5458 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]);
5459 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]);
5460 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5461 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
5462 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5463 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]);
5465 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
5466 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
5467 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
5468 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]);
5469 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]);
5471 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5472 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));
5473 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5474 if (r_glsl_permutation->loc_Color_Pants >= 0)
5476 if (rsurface.texture->pantstexture)
5477 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5479 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
5481 if (r_glsl_permutation->loc_Color_Shirt >= 0)
5483 if (rsurface.texture->shirttexture)
5484 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5486 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
5488 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]);
5489 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
5490 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
5491 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
5492 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5493 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]);
5494 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5495 if (r_glsl_permutation->loc_BounceGridMatrix >= 0) {Matrix4x4_Concat(&tempmatrix, &r_shadow_bouncegridmatrix, &rsurface.matrix);Matrix4x4_ToArrayFloatGL(&tempmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BounceGridMatrix, 1, false, m16f);}
5496 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity);
5498 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
5499 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
5500 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
5501 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
5502 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
5503 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
5504 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
5505 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
5506 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
5507 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
5508 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
5509 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
5510 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
5511 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
5512 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);
5513 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
5514 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
5515 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5516 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5517 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
5518 if (rsurfacepass == RSURFPASS_BACKGROUND)
5520 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);
5521 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);
5522 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);
5526 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);
5528 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
5529 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
5530 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
5531 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
5532 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5534 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture );
5535 if (rsurface.rtlight)
5537 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
5538 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
5541 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
5544 case RENDERPATH_GL13:
5545 case RENDERPATH_GL11:
5547 case RENDERPATH_SOFT:
5548 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);
5549 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
5550 R_SetupShader_SetPermutationSoft(mode, permutation);
5551 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
5552 if (mode == SHADERMODE_LIGHTSOURCE)
5554 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
5555 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5556 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5557 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5558 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5559 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5561 // additive passes are only darkened by fog, not tinted
5562 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
5563 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5567 if (mode == SHADERMODE_FLATCOLOR)
5569 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5571 else if (mode == SHADERMODE_LIGHTDIRECTION)
5573 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]);
5574 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5575 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);
5576 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);
5577 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5578 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]);
5579 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5583 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5584 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5585 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);
5586 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);
5587 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5589 // additive passes are only darkened by fog, not tinted
5590 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5591 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
5593 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5594 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);
5595 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5596 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5597 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]);
5598 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]);
5599 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5600 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
5601 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5602 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
5604 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
5605 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
5606 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
5607 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5608 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]);
5610 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5611 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));
5612 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5613 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
5615 if (rsurface.texture->pantstexture)
5616 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5618 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
5620 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
5622 if (rsurface.texture->shirttexture)
5623 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5625 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
5627 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5628 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
5629 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
5630 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
5631 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5632 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5633 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5635 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
5636 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
5637 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
5638 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
5639 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
5640 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
5641 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
5642 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
5643 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
5644 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
5645 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
5646 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5647 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
5648 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
5649 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5650 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5651 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
5652 if (rsurfacepass == RSURFPASS_BACKGROUND)
5654 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5655 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5656 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5660 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5662 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
5663 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
5664 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
5665 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
5666 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5668 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
5669 if (rsurface.rtlight)
5671 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
5672 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
5679 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
5681 // select a permutation of the lighting shader appropriate to this
5682 // combination of texture, entity, light source, and fogging, only use the
5683 // minimum features necessary to avoid wasting rendering time in the
5684 // fragment shader on features that are not being used
5685 unsigned int permutation = 0;
5686 unsigned int mode = 0;
5687 const float *lightcolorbase = rtlight->currentcolor;
5688 float ambientscale = rtlight->ambientscale;
5689 float diffusescale = rtlight->diffusescale;
5690 float specularscale = rtlight->specularscale;
5691 // this is the location of the light in view space
5692 vec3_t viewlightorigin;
5693 // this transforms from view space (camera) to light space (cubemap)
5694 matrix4x4_t viewtolight;
5695 matrix4x4_t lighttoview;
5696 float viewtolight16f[16];
5697 float range = 1.0f / r_shadow_deferred_8bitrange.value;
5699 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
5700 if (rtlight->currentcubemap != r_texture_whitecube)
5701 permutation |= SHADERPERMUTATION_CUBEFILTER;
5702 if (diffusescale > 0)
5703 permutation |= SHADERPERMUTATION_DIFFUSE;
5704 if (specularscale > 0)
5705 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5706 if (r_shadow_usingshadowmap2d)
5708 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5709 if (r_shadow_shadowmapvsdct)
5710 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5712 if (r_shadow_shadowmapsampler)
5713 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5714 if (r_shadow_shadowmappcf > 1)
5715 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5716 else if (r_shadow_shadowmappcf)
5717 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5719 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
5720 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
5721 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
5722 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
5723 switch(vid.renderpath)
5725 case RENDERPATH_D3D9:
5727 R_SetupShader_SetPermutationHLSL(mode, permutation);
5728 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
5729 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
5730 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
5731 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
5732 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
5733 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5734 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5735 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5736 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5737 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5739 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
5740 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthcolortexture );
5741 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
5742 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
5743 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dcolortexture );
5744 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
5747 case RENDERPATH_D3D10:
5748 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5750 case RENDERPATH_D3D11:
5751 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5753 case RENDERPATH_GL20:
5754 case RENDERPATH_GLES2:
5755 R_SetupShader_SetPermutationGLSL(mode, permutation);
5756 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
5757 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
5758 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);
5759 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);
5760 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);
5761 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]);
5762 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]);
5763 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));
5764 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]);
5765 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
5767 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
5768 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
5769 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
5770 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
5771 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );
5772 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
5774 case RENDERPATH_GL13:
5775 case RENDERPATH_GL11:
5777 case RENDERPATH_SOFT:
5778 R_SetupShader_SetPermutationGLSL(mode, permutation);
5779 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
5780 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
5781 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
5782 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
5783 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
5784 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5785 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]);
5786 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));
5787 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5788 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5790 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
5791 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
5792 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
5793 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
5794 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
5795 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
5800 void R_SetupShader_DeferredBounceLight(void)
5802 // array of particle lights that contribute only ambient color
5803 unsigned int permutation = 0;
5804 unsigned int mode = 0;
5805 mode = SHADERMODE_DEFERREDBOUNCELIGHT;
5806 switch(vid.renderpath)
5808 case RENDERPATH_D3D9:
5810 R_SetupShader_SetPermutationHLSL(mode, permutation);
5811 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5812 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5814 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthcolortexture );
5817 case RENDERPATH_D3D10:
5818 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5820 case RENDERPATH_D3D11:
5821 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5823 case RENDERPATH_GL20:
5824 case RENDERPATH_GLES2:
5825 R_SetupShader_SetPermutationGLSL(mode, permutation);
5826 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]);
5827 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
5829 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
5831 case RENDERPATH_GL13:
5832 case RENDERPATH_GL11:
5834 case RENDERPATH_SOFT:
5835 R_SetupShader_SetPermutationGLSL(mode, permutation);
5836 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5837 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5839 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
5844 #define SKINFRAME_HASH 1024
5848 int loadsequence; // incremented each level change
5849 memexpandablearray_t array;
5850 skinframe_t *hash[SKINFRAME_HASH];
5853 r_skinframe_t r_skinframe;
5855 void R_SkinFrame_PrepareForPurge(void)
5857 r_skinframe.loadsequence++;
5858 // wrap it without hitting zero
5859 if (r_skinframe.loadsequence >= 200)
5860 r_skinframe.loadsequence = 1;
5863 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
5867 // mark the skinframe as used for the purging code
5868 skinframe->loadsequence = r_skinframe.loadsequence;
5871 void R_SkinFrame_Purge(void)
5875 for (i = 0;i < SKINFRAME_HASH;i++)
5877 for (s = r_skinframe.hash[i];s;s = s->next)
5879 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
5881 if (s->merged == s->base)
5883 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
5884 R_PurgeTexture(s->stain );s->stain = NULL;
5885 R_PurgeTexture(s->merged);s->merged = NULL;
5886 R_PurgeTexture(s->base );s->base = NULL;
5887 R_PurgeTexture(s->pants );s->pants = NULL;
5888 R_PurgeTexture(s->shirt );s->shirt = NULL;
5889 R_PurgeTexture(s->nmap );s->nmap = NULL;
5890 R_PurgeTexture(s->gloss );s->gloss = NULL;
5891 R_PurgeTexture(s->glow );s->glow = NULL;
5892 R_PurgeTexture(s->fog );s->fog = NULL;
5893 R_PurgeTexture(s->reflect);s->reflect = NULL;
5894 s->loadsequence = 0;
5900 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
5902 char basename[MAX_QPATH];
5904 Image_StripImageExtension(name, basename, sizeof(basename));
5906 if( last == NULL ) {
5908 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5909 item = r_skinframe.hash[hashindex];
5914 // linearly search through the hash bucket
5915 for( ; item ; item = item->next ) {
5916 if( !strcmp( item->basename, basename ) ) {
5923 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
5927 char basename[MAX_QPATH];
5929 Image_StripImageExtension(name, basename, sizeof(basename));
5931 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5932 for (item = r_skinframe.hash[hashindex];item;item = item->next)
5933 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
5937 rtexture_t *dyntexture;
5938 // check whether its a dynamic texture
5939 dyntexture = CL_GetDynTexture( basename );
5940 if (!add && !dyntexture)
5942 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
5943 memset(item, 0, sizeof(*item));
5944 strlcpy(item->basename, basename, sizeof(item->basename));
5945 item->base = dyntexture; // either NULL or dyntexture handle
5946 item->textureflags = textureflags;
5947 item->comparewidth = comparewidth;
5948 item->compareheight = compareheight;
5949 item->comparecrc = comparecrc;
5950 item->next = r_skinframe.hash[hashindex];
5951 r_skinframe.hash[hashindex] = item;
5953 else if( item->base == NULL )
5955 rtexture_t *dyntexture;
5956 // check whether its a dynamic texture
5957 // 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]
5958 dyntexture = CL_GetDynTexture( basename );
5959 item->base = dyntexture; // either NULL or dyntexture handle
5962 R_SkinFrame_MarkUsed(item);
5966 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
5968 unsigned long long avgcolor[5], wsum; \
5976 for(pix = 0; pix < cnt; ++pix) \
5979 for(comp = 0; comp < 3; ++comp) \
5981 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
5984 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5986 for(comp = 0; comp < 3; ++comp) \
5987 avgcolor[comp] += getpixel * w; \
5990 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5991 avgcolor[4] += getpixel; \
5993 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
5995 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
5996 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
5997 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
5998 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
6001 extern cvar_t gl_picmip;
6002 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
6005 unsigned char *pixels;
6006 unsigned char *bumppixels;
6007 unsigned char *basepixels = NULL;
6008 int basepixels_width = 0;
6009 int basepixels_height = 0;
6010 skinframe_t *skinframe;
6011 rtexture_t *ddsbase = NULL;
6012 qboolean ddshasalpha = false;
6013 float ddsavgcolor[4];
6014 char basename[MAX_QPATH];
6015 int miplevel = R_PicmipForFlags(textureflags);
6016 int savemiplevel = miplevel;
6019 if (cls.state == ca_dedicated)
6022 // return an existing skinframe if already loaded
6023 // if loading of the first image fails, don't make a new skinframe as it
6024 // would cause all future lookups of this to be missing
6025 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
6026 if (skinframe && skinframe->base)
6029 Image_StripImageExtension(name, basename, sizeof(basename));
6031 // check for DDS texture file first
6032 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
6034 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
6035 if (basepixels == NULL)
6039 // FIXME handle miplevel
6041 if (developer_loading.integer)
6042 Con_Printf("loading skin \"%s\"\n", name);
6044 // we've got some pixels to store, so really allocate this new texture now
6046 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
6047 skinframe->stain = NULL;
6048 skinframe->merged = NULL;
6049 skinframe->base = NULL;
6050 skinframe->pants = NULL;
6051 skinframe->shirt = NULL;
6052 skinframe->nmap = NULL;
6053 skinframe->gloss = NULL;
6054 skinframe->glow = NULL;
6055 skinframe->fog = NULL;
6056 skinframe->reflect = NULL;
6057 skinframe->hasalpha = false;
6061 skinframe->base = ddsbase;
6062 skinframe->hasalpha = ddshasalpha;
6063 VectorCopy(ddsavgcolor, skinframe->avgcolor);
6064 if (r_loadfog && skinframe->hasalpha)
6065 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
6066 //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]);
6070 basepixels_width = image_width;
6071 basepixels_height = image_height;
6072 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);
6073 if (textureflags & TEXF_ALPHA)
6075 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
6077 if (basepixels[j] < 255)
6079 skinframe->hasalpha = true;
6083 if (r_loadfog && skinframe->hasalpha)
6085 // has transparent pixels
6086 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6087 for (j = 0;j < image_width * image_height * 4;j += 4)
6092 pixels[j+3] = basepixels[j+3];
6094 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);
6098 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
6099 //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]);
6100 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
6101 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
6102 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
6103 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
6108 mymiplevel = savemiplevel;
6109 if (r_loadnormalmap)
6110 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);
6111 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6113 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6114 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6115 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6116 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6119 // _norm is the name used by tenebrae and has been adopted as standard
6120 if (r_loadnormalmap && skinframe->nmap == NULL)
6122 mymiplevel = savemiplevel;
6123 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6125 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);
6129 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6131 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6132 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
6133 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);
6135 Mem_Free(bumppixels);
6137 else if (r_shadow_bumpscale_basetexture.value > 0)
6139 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
6140 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
6141 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);
6144 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
6145 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
6148 // _luma is supported only for tenebrae compatibility
6149 // _glow is the preferred name
6150 mymiplevel = savemiplevel;
6151 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))))
6153 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);
6154 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
6155 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
6156 Mem_Free(pixels);pixels = NULL;
6159 mymiplevel = savemiplevel;
6160 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6162 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);
6163 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
6164 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
6169 mymiplevel = savemiplevel;
6170 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6172 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);
6173 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
6174 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
6179 mymiplevel = savemiplevel;
6180 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6182 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);
6183 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
6184 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
6189 mymiplevel = savemiplevel;
6190 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6192 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);
6193 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
6194 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
6200 Mem_Free(basepixels);
6205 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
6206 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
6209 unsigned char *temp1, *temp2;
6210 skinframe_t *skinframe;
6212 if (cls.state == ca_dedicated)
6215 // if already loaded just return it, otherwise make a new skinframe
6216 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
6217 if (skinframe && skinframe->base)
6220 skinframe->stain = NULL;
6221 skinframe->merged = NULL;
6222 skinframe->base = NULL;
6223 skinframe->pants = NULL;
6224 skinframe->shirt = NULL;
6225 skinframe->nmap = NULL;
6226 skinframe->gloss = NULL;
6227 skinframe->glow = NULL;
6228 skinframe->fog = NULL;
6229 skinframe->reflect = NULL;
6230 skinframe->hasalpha = false;
6232 // if no data was provided, then clearly the caller wanted to get a blank skinframe
6236 if (developer_loading.integer)
6237 Con_Printf("loading 32bit skin \"%s\"\n", name);
6239 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
6241 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6242 temp2 = temp1 + width * height * 4;
6243 Image_HeightmapToNormalmap_BGRA(skindata, 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, (textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
6247 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
6248 if (textureflags & TEXF_ALPHA)
6250 for (i = 3;i < width * height * 4;i += 4)
6252 if (skindata[i] < 255)
6254 skinframe->hasalpha = true;
6258 if (r_loadfog && skinframe->hasalpha)
6260 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
6261 memcpy(fogpixels, skindata, width * height * 4);
6262 for (i = 0;i < width * height * 4;i += 4)
6263 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
6264 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
6265 Mem_Free(fogpixels);
6269 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
6270 //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]);
6275 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
6279 skinframe_t *skinframe;
6281 if (cls.state == ca_dedicated)
6284 // if already loaded just return it, otherwise make a new skinframe
6285 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6286 if (skinframe && skinframe->base)
6289 skinframe->stain = NULL;
6290 skinframe->merged = NULL;
6291 skinframe->base = NULL;
6292 skinframe->pants = NULL;
6293 skinframe->shirt = NULL;
6294 skinframe->nmap = NULL;
6295 skinframe->gloss = NULL;
6296 skinframe->glow = NULL;
6297 skinframe->fog = NULL;
6298 skinframe->reflect = NULL;
6299 skinframe->hasalpha = false;
6301 // if no data was provided, then clearly the caller wanted to get a blank skinframe
6305 if (developer_loading.integer)
6306 Con_Printf("loading quake skin \"%s\"\n", name);
6308 // 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)
6309 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
6310 memcpy(skinframe->qpixels, skindata, width*height);
6311 skinframe->qwidth = width;
6312 skinframe->qheight = height;
6315 for (i = 0;i < width * height;i++)
6316 featuresmask |= palette_featureflags[skindata[i]];
6318 skinframe->hasalpha = false;
6319 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
6320 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
6321 skinframe->qgeneratemerged = true;
6322 skinframe->qgeneratebase = skinframe->qhascolormapping;
6323 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
6325 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
6326 //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]);
6331 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
6335 unsigned char *skindata;
6337 if (!skinframe->qpixels)
6340 if (!skinframe->qhascolormapping)
6341 colormapped = false;
6345 if (!skinframe->qgeneratebase)
6350 if (!skinframe->qgeneratemerged)
6354 width = skinframe->qwidth;
6355 height = skinframe->qheight;
6356 skindata = skinframe->qpixels;
6358 if (skinframe->qgeneratenmap)
6360 unsigned char *temp1, *temp2;
6361 skinframe->qgeneratenmap = false;
6362 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6363 temp2 = temp1 + width * height * 4;
6364 // use either a custom palette or the quake palette
6365 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
6366 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6367 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);
6371 if (skinframe->qgenerateglow)
6373 skinframe->qgenerateglow = false;
6374 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
6379 skinframe->qgeneratebase = false;
6380 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);
6381 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
6382 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
6386 skinframe->qgeneratemerged = false;
6387 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);
6390 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
6392 Mem_Free(skinframe->qpixels);
6393 skinframe->qpixels = NULL;
6397 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)
6400 skinframe_t *skinframe;
6402 if (cls.state == ca_dedicated)
6405 // if already loaded just return it, otherwise make a new skinframe
6406 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6407 if (skinframe && skinframe->base)
6410 skinframe->stain = NULL;
6411 skinframe->merged = NULL;
6412 skinframe->base = NULL;
6413 skinframe->pants = NULL;
6414 skinframe->shirt = NULL;
6415 skinframe->nmap = NULL;
6416 skinframe->gloss = NULL;
6417 skinframe->glow = NULL;
6418 skinframe->fog = NULL;
6419 skinframe->reflect = NULL;
6420 skinframe->hasalpha = false;
6422 // if no data was provided, then clearly the caller wanted to get a blank skinframe
6426 if (developer_loading.integer)
6427 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
6429 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
6430 if (textureflags & TEXF_ALPHA)
6432 for (i = 0;i < width * height;i++)
6434 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
6436 skinframe->hasalpha = true;
6440 if (r_loadfog && skinframe->hasalpha)
6441 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
6444 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
6445 //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]);
6450 skinframe_t *R_SkinFrame_LoadMissing(void)
6452 skinframe_t *skinframe;
6454 if (cls.state == ca_dedicated)
6457 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
6458 skinframe->stain = NULL;
6459 skinframe->merged = NULL;
6460 skinframe->base = NULL;
6461 skinframe->pants = NULL;
6462 skinframe->shirt = NULL;
6463 skinframe->nmap = NULL;
6464 skinframe->gloss = NULL;
6465 skinframe->glow = NULL;
6466 skinframe->fog = NULL;
6467 skinframe->reflect = NULL;
6468 skinframe->hasalpha = false;
6470 skinframe->avgcolor[0] = rand() / RAND_MAX;
6471 skinframe->avgcolor[1] = rand() / RAND_MAX;
6472 skinframe->avgcolor[2] = rand() / RAND_MAX;
6473 skinframe->avgcolor[3] = 1;
6478 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
6479 typedef struct suffixinfo_s
6482 qboolean flipx, flipy, flipdiagonal;
6485 static suffixinfo_t suffix[3][6] =
6488 {"px", false, false, false},
6489 {"nx", false, false, false},
6490 {"py", false, false, false},
6491 {"ny", false, false, false},
6492 {"pz", false, false, false},
6493 {"nz", false, false, false}
6496 {"posx", false, false, false},
6497 {"negx", false, false, false},
6498 {"posy", false, false, false},
6499 {"negy", false, false, false},
6500 {"posz", false, false, false},
6501 {"negz", false, false, false}
6504 {"rt", true, false, true},
6505 {"lf", false, true, true},
6506 {"ft", true, true, false},
6507 {"bk", false, false, false},
6508 {"up", true, false, true},
6509 {"dn", true, false, true}
6513 static int componentorder[4] = {0, 1, 2, 3};
6515 rtexture_t *R_LoadCubemap(const char *basename)
6517 int i, j, cubemapsize;
6518 unsigned char *cubemappixels, *image_buffer;
6519 rtexture_t *cubemaptexture;
6521 // must start 0 so the first loadimagepixels has no requested width/height
6523 cubemappixels = NULL;
6524 cubemaptexture = NULL;
6525 // keep trying different suffix groups (posx, px, rt) until one loads
6526 for (j = 0;j < 3 && !cubemappixels;j++)
6528 // load the 6 images in the suffix group
6529 for (i = 0;i < 6;i++)
6531 // generate an image name based on the base and and suffix
6532 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
6534 if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
6536 // an image loaded, make sure width and height are equal
6537 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
6539 // if this is the first image to load successfully, allocate the cubemap memory
6540 if (!cubemappixels && image_width >= 1)
6542 cubemapsize = image_width;
6543 // note this clears to black, so unavailable sides are black
6544 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
6546 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
6548 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);
6551 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
6553 Mem_Free(image_buffer);
6557 // if a cubemap loaded, upload it
6560 if (developer_loading.integer)
6561 Con_Printf("loading cubemap \"%s\"\n", basename);
6563 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6564 Mem_Free(cubemappixels);
6568 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
6569 if (developer_loading.integer)
6571 Con_Printf("(tried tried images ");
6572 for (j = 0;j < 3;j++)
6573 for (i = 0;i < 6;i++)
6574 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
6575 Con_Print(" and was unable to find any of them).\n");
6578 return cubemaptexture;
6581 rtexture_t *R_GetCubemap(const char *basename)
6584 for (i = 0;i < r_texture_numcubemaps;i++)
6585 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
6586 return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
6587 if (i >= MAX_CUBEMAPS)
6588 return r_texture_whitecube;
6589 r_texture_numcubemaps++;
6590 strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
6591 r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
6592 return r_texture_cubemaps[i].texture;
6595 void R_FreeCubemaps(void)
6598 for (i = 0;i < r_texture_numcubemaps;i++)
6600 if (developer_loading.integer)
6601 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
6602 if (r_texture_cubemaps[i].texture)
6603 R_FreeTexture(r_texture_cubemaps[i].texture);
6605 r_texture_numcubemaps = 0;
6608 void R_Main_FreeViewCache(void)
6610 if (r_refdef.viewcache.entityvisible)
6611 Mem_Free(r_refdef.viewcache.entityvisible);
6612 if (r_refdef.viewcache.world_pvsbits)
6613 Mem_Free(r_refdef.viewcache.world_pvsbits);
6614 if (r_refdef.viewcache.world_leafvisible)
6615 Mem_Free(r_refdef.viewcache.world_leafvisible);
6616 if (r_refdef.viewcache.world_surfacevisible)
6617 Mem_Free(r_refdef.viewcache.world_surfacevisible);
6618 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
6621 void R_Main_ResizeViewCache(void)
6623 int numentities = r_refdef.scene.numentities;
6624 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
6625 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
6626 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
6627 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
6628 if (r_refdef.viewcache.maxentities < numentities)
6630 r_refdef.viewcache.maxentities = numentities;
6631 if (r_refdef.viewcache.entityvisible)
6632 Mem_Free(r_refdef.viewcache.entityvisible);
6633 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
6635 if (r_refdef.viewcache.world_numclusters != numclusters)
6637 r_refdef.viewcache.world_numclusters = numclusters;
6638 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
6639 if (r_refdef.viewcache.world_pvsbits)
6640 Mem_Free(r_refdef.viewcache.world_pvsbits);
6641 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
6643 if (r_refdef.viewcache.world_numleafs != numleafs)
6645 r_refdef.viewcache.world_numleafs = numleafs;
6646 if (r_refdef.viewcache.world_leafvisible)
6647 Mem_Free(r_refdef.viewcache.world_leafvisible);
6648 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
6650 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
6652 r_refdef.viewcache.world_numsurfaces = numsurfaces;
6653 if (r_refdef.viewcache.world_surfacevisible)
6654 Mem_Free(r_refdef.viewcache.world_surfacevisible);
6655 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
6659 extern rtexture_t *loadingscreentexture;
6660 void gl_main_start(void)
6662 loadingscreentexture = NULL;
6663 r_texture_blanknormalmap = NULL;
6664 r_texture_white = NULL;
6665 r_texture_grey128 = NULL;
6666 r_texture_black = NULL;
6667 r_texture_whitecube = NULL;
6668 r_texture_normalizationcube = NULL;
6669 r_texture_fogattenuation = NULL;
6670 r_texture_fogheighttexture = NULL;
6671 r_texture_gammaramps = NULL;
6672 r_texture_numcubemaps = 0;
6674 r_loaddds = r_texture_dds_load.integer != 0;
6675 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
6677 switch(vid.renderpath)
6679 case RENDERPATH_GL20:
6680 case RENDERPATH_D3D9:
6681 case RENDERPATH_D3D10:
6682 case RENDERPATH_D3D11:
6683 case RENDERPATH_SOFT:
6684 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6685 Cvar_SetValueQuick(&gl_combine, 1);
6686 Cvar_SetValueQuick(&r_glsl, 1);
6687 r_loadnormalmap = true;
6691 case RENDERPATH_GL13:
6692 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6693 Cvar_SetValueQuick(&gl_combine, 1);
6694 Cvar_SetValueQuick(&r_glsl, 0);
6695 r_loadnormalmap = false;
6696 r_loadgloss = false;
6699 case RENDERPATH_GL11:
6700 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6701 Cvar_SetValueQuick(&gl_combine, 0);
6702 Cvar_SetValueQuick(&r_glsl, 0);
6703 r_loadnormalmap = false;
6704 r_loadgloss = false;
6707 case RENDERPATH_GLES2:
6708 Cvar_SetValueQuick(&r_textureunits, 1);
6709 Cvar_SetValueQuick(&gl_combine, 1);
6710 Cvar_SetValueQuick(&r_glsl, 1);
6711 r_loadnormalmap = true;
6712 r_loadgloss = false;
6718 R_FrameData_Reset();
6722 memset(r_queries, 0, sizeof(r_queries));
6724 r_qwskincache = NULL;
6725 r_qwskincache_size = 0;
6727 // set up r_skinframe loading system for textures
6728 memset(&r_skinframe, 0, sizeof(r_skinframe));
6729 r_skinframe.loadsequence = 1;
6730 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
6732 r_main_texturepool = R_AllocTexturePool();
6733 R_BuildBlankTextures();
6735 if (vid.support.arb_texture_cube_map)
6738 R_BuildNormalizationCube();
6740 r_texture_fogattenuation = NULL;
6741 r_texture_fogheighttexture = NULL;
6742 r_texture_gammaramps = NULL;
6743 //r_texture_fogintensity = NULL;
6744 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6745 memset(&r_waterstate, 0, sizeof(r_waterstate));
6746 r_glsl_permutation = NULL;
6747 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
6748 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
6749 glslshaderstring = NULL;
6751 r_hlsl_permutation = NULL;
6752 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
6753 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
6755 hlslshaderstring = NULL;
6756 memset(&r_svbsp, 0, sizeof (r_svbsp));
6758 r_refdef.fogmasktable_density = 0;
6761 void gl_main_shutdown(void)
6764 R_FrameData_Reset();
6766 R_Main_FreeViewCache();
6768 switch(vid.renderpath)
6770 case RENDERPATH_GL11:
6771 case RENDERPATH_GL13:
6772 case RENDERPATH_GL20:
6773 case RENDERPATH_GLES2:
6775 qglDeleteQueriesARB(r_maxqueries, r_queries);
6777 case RENDERPATH_D3D9:
6778 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6780 case RENDERPATH_D3D10:
6781 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6783 case RENDERPATH_D3D11:
6784 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6786 case RENDERPATH_SOFT:
6792 memset(r_queries, 0, sizeof(r_queries));
6794 r_qwskincache = NULL;
6795 r_qwskincache_size = 0;
6797 // clear out the r_skinframe state
6798 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
6799 memset(&r_skinframe, 0, sizeof(r_skinframe));
6802 Mem_Free(r_svbsp.nodes);
6803 memset(&r_svbsp, 0, sizeof (r_svbsp));
6804 R_FreeTexturePool(&r_main_texturepool);
6805 loadingscreentexture = NULL;
6806 r_texture_blanknormalmap = NULL;
6807 r_texture_white = NULL;
6808 r_texture_grey128 = NULL;
6809 r_texture_black = NULL;
6810 r_texture_whitecube = NULL;
6811 r_texture_normalizationcube = NULL;
6812 r_texture_fogattenuation = NULL;
6813 r_texture_fogheighttexture = NULL;
6814 r_texture_gammaramps = NULL;
6815 r_texture_numcubemaps = 0;
6816 //r_texture_fogintensity = NULL;
6817 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6818 memset(&r_waterstate, 0, sizeof(r_waterstate));
6821 r_glsl_permutation = NULL;
6822 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
6823 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
6824 glslshaderstring = NULL;
6826 r_hlsl_permutation = NULL;
6827 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
6828 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
6830 hlslshaderstring = NULL;
6833 extern void CL_ParseEntityLump(char *entitystring);
6834 void gl_main_newmap(void)
6836 // FIXME: move this code to client
6837 char *entities, entname[MAX_QPATH];
6839 Mem_Free(r_qwskincache);
6840 r_qwskincache = NULL;
6841 r_qwskincache_size = 0;
6844 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
6845 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
6847 CL_ParseEntityLump(entities);
6851 if (cl.worldmodel->brush.entities)
6852 CL_ParseEntityLump(cl.worldmodel->brush.entities);
6854 R_Main_FreeViewCache();
6856 R_FrameData_Reset();
6859 void GL_Main_Init(void)
6861 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
6863 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
6864 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
6865 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
6866 if (gamemode == GAME_NEHAHRA)
6868 Cvar_RegisterVariable (&gl_fogenable);
6869 Cvar_RegisterVariable (&gl_fogdensity);
6870 Cvar_RegisterVariable (&gl_fogred);
6871 Cvar_RegisterVariable (&gl_foggreen);
6872 Cvar_RegisterVariable (&gl_fogblue);
6873 Cvar_RegisterVariable (&gl_fogstart);
6874 Cvar_RegisterVariable (&gl_fogend);
6875 Cvar_RegisterVariable (&gl_skyclip);
6877 Cvar_RegisterVariable(&r_motionblur);
6878 Cvar_RegisterVariable(&r_motionblur_maxblur);
6879 Cvar_RegisterVariable(&r_motionblur_bmin);
6880 Cvar_RegisterVariable(&r_motionblur_vmin);
6881 Cvar_RegisterVariable(&r_motionblur_vmax);
6882 Cvar_RegisterVariable(&r_motionblur_vcoeff);
6883 Cvar_RegisterVariable(&r_motionblur_randomize);
6884 Cvar_RegisterVariable(&r_damageblur);
6885 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
6886 Cvar_RegisterVariable(&r_equalize_entities_minambient);
6887 Cvar_RegisterVariable(&r_equalize_entities_by);
6888 Cvar_RegisterVariable(&r_equalize_entities_to);
6889 Cvar_RegisterVariable(&r_depthfirst);
6890 Cvar_RegisterVariable(&r_useinfinitefarclip);
6891 Cvar_RegisterVariable(&r_farclip_base);
6892 Cvar_RegisterVariable(&r_farclip_world);
6893 Cvar_RegisterVariable(&r_nearclip);
6894 Cvar_RegisterVariable(&r_showbboxes);
6895 Cvar_RegisterVariable(&r_showsurfaces);
6896 Cvar_RegisterVariable(&r_showtris);
6897 Cvar_RegisterVariable(&r_shownormals);
6898 Cvar_RegisterVariable(&r_showlighting);
6899 Cvar_RegisterVariable(&r_showshadowvolumes);
6900 Cvar_RegisterVariable(&r_showcollisionbrushes);
6901 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
6902 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
6903 Cvar_RegisterVariable(&r_showdisabledepthtest);
6904 Cvar_RegisterVariable(&r_drawportals);
6905 Cvar_RegisterVariable(&r_drawentities);
6906 Cvar_RegisterVariable(&r_draw2d);
6907 Cvar_RegisterVariable(&r_drawworld);
6908 Cvar_RegisterVariable(&r_cullentities_trace);
6909 Cvar_RegisterVariable(&r_cullentities_trace_samples);
6910 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
6911 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
6912 Cvar_RegisterVariable(&r_cullentities_trace_delay);
6913 Cvar_RegisterVariable(&r_drawviewmodel);
6914 Cvar_RegisterVariable(&r_drawexteriormodel);
6915 Cvar_RegisterVariable(&r_speeds);
6916 Cvar_RegisterVariable(&r_fullbrights);
6917 Cvar_RegisterVariable(&r_wateralpha);
6918 Cvar_RegisterVariable(&r_dynamic);
6919 Cvar_RegisterVariable(&r_fakelight);
6920 Cvar_RegisterVariable(&r_fakelight_intensity);
6921 Cvar_RegisterVariable(&r_fullbright);
6922 Cvar_RegisterVariable(&r_shadows);
6923 Cvar_RegisterVariable(&r_shadows_darken);
6924 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
6925 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
6926 Cvar_RegisterVariable(&r_shadows_throwdistance);
6927 Cvar_RegisterVariable(&r_shadows_throwdirection);
6928 Cvar_RegisterVariable(&r_shadows_focus);
6929 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
6930 Cvar_RegisterVariable(&r_q1bsp_skymasking);
6931 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
6932 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
6933 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
6934 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
6935 Cvar_RegisterVariable(&r_fog_exp2);
6936 Cvar_RegisterVariable(&r_drawfog);
6937 Cvar_RegisterVariable(&r_transparentdepthmasking);
6938 Cvar_RegisterVariable(&r_texture_dds_load);
6939 Cvar_RegisterVariable(&r_texture_dds_save);
6940 Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
6941 Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
6942 Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
6943 Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
6944 Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
6945 Cvar_RegisterVariable(&r_textureunits);
6946 Cvar_RegisterVariable(&gl_combine);
6947 Cvar_RegisterVariable(&r_glsl);
6948 Cvar_RegisterVariable(&r_glsl_deluxemapping);
6949 Cvar_RegisterVariable(&r_glsl_offsetmapping);
6950 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
6951 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
6952 Cvar_RegisterVariable(&r_glsl_postprocess);
6953 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
6954 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
6955 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
6956 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
6957 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
6958 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
6959 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
6960 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
6962 Cvar_RegisterVariable(&r_water);
6963 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
6964 Cvar_RegisterVariable(&r_water_clippingplanebias);
6965 Cvar_RegisterVariable(&r_water_refractdistort);
6966 Cvar_RegisterVariable(&r_water_reflectdistort);
6967 Cvar_RegisterVariable(&r_water_scissormode);
6968 Cvar_RegisterVariable(&r_lerpsprites);
6969 Cvar_RegisterVariable(&r_lerpmodels);
6970 Cvar_RegisterVariable(&r_lerplightstyles);
6971 Cvar_RegisterVariable(&r_waterscroll);
6972 Cvar_RegisterVariable(&r_bloom);
6973 Cvar_RegisterVariable(&r_bloom_colorscale);
6974 Cvar_RegisterVariable(&r_bloom_brighten);
6975 Cvar_RegisterVariable(&r_bloom_blur);
6976 Cvar_RegisterVariable(&r_bloom_resolution);
6977 Cvar_RegisterVariable(&r_bloom_colorexponent);
6978 Cvar_RegisterVariable(&r_bloom_colorsubtract);
6979 Cvar_RegisterVariable(&r_hdr);
6980 Cvar_RegisterVariable(&r_hdr_scenebrightness);
6981 Cvar_RegisterVariable(&r_hdr_glowintensity);
6982 Cvar_RegisterVariable(&r_hdr_range);
6983 Cvar_RegisterVariable(&r_hdr_irisadaptation);
6984 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
6985 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
6986 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
6987 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
6988 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
6989 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
6990 Cvar_RegisterVariable(&developer_texturelogging);
6991 Cvar_RegisterVariable(&gl_lightmaps);
6992 Cvar_RegisterVariable(&r_test);
6993 Cvar_RegisterVariable(&r_glsl_saturation);
6994 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
6995 Cvar_RegisterVariable(&r_framedatasize);
6996 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
6997 Cvar_SetValue("r_fullbrights", 0);
6998 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
7000 Cvar_RegisterVariable(&r_track_sprites);
7001 Cvar_RegisterVariable(&r_track_sprites_flags);
7002 Cvar_RegisterVariable(&r_track_sprites_scalew);
7003 Cvar_RegisterVariable(&r_track_sprites_scaleh);
7004 Cvar_RegisterVariable(&r_overheadsprites_perspective);
7005 Cvar_RegisterVariable(&r_overheadsprites_pushback);
7006 Cvar_RegisterVariable(&r_overheadsprites_scalex);
7007 Cvar_RegisterVariable(&r_overheadsprites_scaley);
7010 extern void R_Textures_Init(void);
7011 extern void GL_Draw_Init(void);
7012 extern void GL_Main_Init(void);
7013 extern void R_Shadow_Init(void);
7014 extern void R_Sky_Init(void);
7015 extern void GL_Surf_Init(void);
7016 extern void R_Particles_Init(void);
7017 extern void R_Explosion_Init(void);
7018 extern void gl_backend_init(void);
7019 extern void Sbar_Init(void);
7020 extern void R_LightningBeams_Init(void);
7021 extern void Mod_RenderInit(void);
7022 extern void Font_Init(void);
7024 void Render_Init(void)
7037 R_LightningBeams_Init();
7046 extern char *ENGINE_EXTENSIONS;
7049 gl_renderer = (const char *)qglGetString(GL_RENDERER);
7050 gl_vendor = (const char *)qglGetString(GL_VENDOR);
7051 gl_version = (const char *)qglGetString(GL_VERSION);
7052 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
7056 if (!gl_platformextensions)
7057 gl_platformextensions = "";
7059 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
7060 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
7061 Con_Printf("GL_VERSION: %s\n", gl_version);
7062 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
7063 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
7065 VID_CheckExtensions();
7067 // LordHavoc: report supported extensions
7068 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
7070 // clear to black (loading plaque will be seen over this)
7071 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
7074 int R_CullBox(const vec3_t mins, const vec3_t maxs)
7078 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7080 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
7083 p = r_refdef.view.frustum + i;
7088 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7092 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7096 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7100 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7104 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7108 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7112 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7116 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7124 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
7128 for (i = 0;i < numplanes;i++)
7135 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7139 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7143 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7147 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7151 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7155 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7159 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7163 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7171 //==================================================================================
7173 // LordHavoc: this stores temporary data used within the same frame
7175 typedef struct r_framedata_mem_s
7177 struct r_framedata_mem_s *purge; // older mem block to free on next frame
7178 size_t size; // how much usable space
7179 size_t current; // how much space in use
7180 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
7181 size_t wantedsize; // how much space was allocated
7182 unsigned char *data; // start of real data (16byte aligned)
7186 static r_framedata_mem_t *r_framedata_mem;
7188 void R_FrameData_Reset(void)
7190 while (r_framedata_mem)
7192 r_framedata_mem_t *next = r_framedata_mem->purge;
7193 Mem_Free(r_framedata_mem);
7194 r_framedata_mem = next;
7198 void R_FrameData_Resize(void)
7201 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
7202 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
7203 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
7205 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
7206 newmem->wantedsize = wantedsize;
7207 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
7208 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
7209 newmem->current = 0;
7211 newmem->purge = r_framedata_mem;
7212 r_framedata_mem = newmem;
7216 void R_FrameData_NewFrame(void)
7218 R_FrameData_Resize();
7219 if (!r_framedata_mem)
7221 // if we ran out of space on the last frame, free the old memory now
7222 while (r_framedata_mem->purge)
7224 // repeatedly remove the second item in the list, leaving only head
7225 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
7226 Mem_Free(r_framedata_mem->purge);
7227 r_framedata_mem->purge = next;
7229 // reset the current mem pointer
7230 r_framedata_mem->current = 0;
7231 r_framedata_mem->mark = 0;
7234 void *R_FrameData_Alloc(size_t size)
7238 // align to 16 byte boundary - the data pointer is already aligned, so we
7239 // only need to ensure the size of every allocation is also aligned
7240 size = (size + 15) & ~15;
7242 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
7244 // emergency - we ran out of space, allocate more memory
7245 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
7246 R_FrameData_Resize();
7249 data = r_framedata_mem->data + r_framedata_mem->current;
7250 r_framedata_mem->current += size;
7252 // count the usage for stats
7253 r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
7254 r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
7256 return (void *)data;
7259 void *R_FrameData_Store(size_t size, void *data)
7261 void *d = R_FrameData_Alloc(size);
7263 memcpy(d, data, size);
7267 void R_FrameData_SetMark(void)
7269 if (!r_framedata_mem)
7271 r_framedata_mem->mark = r_framedata_mem->current;
7274 void R_FrameData_ReturnToMark(void)
7276 if (!r_framedata_mem)
7278 r_framedata_mem->current = r_framedata_mem->mark;
7281 //==================================================================================
7283 // LordHavoc: animcache originally written by Echon, rewritten since then
7286 * Animation cache prevents re-generating mesh data for an animated model
7287 * multiple times in one frame for lighting, shadowing, reflections, etc.
7290 void R_AnimCache_Free(void)
7294 void R_AnimCache_ClearCache(void)
7297 entity_render_t *ent;
7299 for (i = 0;i < r_refdef.scene.numentities;i++)
7301 ent = r_refdef.scene.entities[i];
7302 ent->animcache_vertex3f = NULL;
7303 ent->animcache_normal3f = NULL;
7304 ent->animcache_svector3f = NULL;
7305 ent->animcache_tvector3f = NULL;
7306 ent->animcache_vertexmesh = NULL;
7307 ent->animcache_vertex3fbuffer = NULL;
7308 ent->animcache_vertexmeshbuffer = NULL;
7312 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
7316 // check if we need the meshbuffers
7317 if (!vid.useinterleavedarrays)
7320 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
7321 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
7322 // TODO: upload vertex3f buffer?
7323 if (ent->animcache_vertexmesh)
7325 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
7326 for (i = 0;i < numvertices;i++)
7327 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7328 if (ent->animcache_svector3f)
7329 for (i = 0;i < numvertices;i++)
7330 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
7331 if (ent->animcache_tvector3f)
7332 for (i = 0;i < numvertices;i++)
7333 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
7334 if (ent->animcache_normal3f)
7335 for (i = 0;i < numvertices;i++)
7336 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
7337 // TODO: upload vertexmeshbuffer?
7341 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
7343 dp_model_t *model = ent->model;
7345 // see if it's already cached this frame
7346 if (ent->animcache_vertex3f)
7348 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
7349 if (wantnormals || wanttangents)
7351 if (ent->animcache_normal3f)
7352 wantnormals = false;
7353 if (ent->animcache_svector3f)
7354 wanttangents = false;
7355 if (wantnormals || wanttangents)
7357 numvertices = model->surfmesh.num_vertices;
7359 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7362 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7363 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7365 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
7366 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7372 // see if this ent is worth caching
7373 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
7375 // get some memory for this entity and generate mesh data
7376 numvertices = model->surfmesh.num_vertices;
7377 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7379 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7382 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7383 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7385 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
7386 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7391 void R_AnimCache_CacheVisibleEntities(void)
7394 qboolean wantnormals = true;
7395 qboolean wanttangents = !r_showsurfaces.integer;
7397 switch(vid.renderpath)
7399 case RENDERPATH_GL20:
7400 case RENDERPATH_D3D9:
7401 case RENDERPATH_D3D10:
7402 case RENDERPATH_D3D11:
7403 case RENDERPATH_GLES2:
7405 case RENDERPATH_GL13:
7406 case RENDERPATH_GL11:
7407 wanttangents = false;
7409 case RENDERPATH_SOFT:
7413 if (r_shownormals.integer)
7414 wanttangents = wantnormals = true;
7416 // TODO: thread this
7417 // NOTE: R_PrepareRTLights() also caches entities
7419 for (i = 0;i < r_refdef.scene.numentities;i++)
7420 if (r_refdef.viewcache.entityvisible[i])
7421 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
7424 //==================================================================================
7426 static void R_View_UpdateEntityLighting (void)
7429 entity_render_t *ent;
7430 vec3_t tempdiffusenormal, avg;
7431 vec_t f, fa, fd, fdd;
7432 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
7434 for (i = 0;i < r_refdef.scene.numentities;i++)
7436 ent = r_refdef.scene.entities[i];
7438 // skip unseen models
7439 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
7443 if (ent->model && ent->model->brush.num_leafs)
7445 // TODO: use modellight for r_ambient settings on world?
7446 VectorSet(ent->modellight_ambient, 0, 0, 0);
7447 VectorSet(ent->modellight_diffuse, 0, 0, 0);
7448 VectorSet(ent->modellight_lightdir, 0, 0, 1);
7452 // fetch the lighting from the worldmodel data
7453 VectorClear(ent->modellight_ambient);
7454 VectorClear(ent->modellight_diffuse);
7455 VectorClear(tempdiffusenormal);
7456 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
7459 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7461 // complete lightning for lit sprites
7462 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
7463 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
7465 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
7466 org[2] = org[2] + r_overheadsprites_pushback.value;
7467 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
7470 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
7472 if(ent->flags & RENDER_EQUALIZE)
7474 // first fix up ambient lighting...
7475 if(r_equalize_entities_minambient.value > 0)
7477 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7480 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
7481 if(fa < r_equalize_entities_minambient.value * fd)
7484 // fa'/fd' = minambient
7485 // fa'+0.25*fd' = fa+0.25*fd
7487 // fa' = fd' * minambient
7488 // fd'*(0.25+minambient) = fa+0.25*fd
7490 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
7491 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
7493 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
7494 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
7495 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
7496 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7501 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
7503 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
7504 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7508 // adjust brightness and saturation to target
7509 avg[0] = avg[1] = avg[2] = fa / f;
7510 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
7511 avg[0] = avg[1] = avg[2] = fd / f;
7512 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
7518 VectorSet(ent->modellight_ambient, 1, 1, 1);
7520 // move the light direction into modelspace coordinates for lighting code
7521 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
7522 if(VectorLength2(ent->modellight_lightdir) == 0)
7523 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
7524 VectorNormalize(ent->modellight_lightdir);
7528 #define MAX_LINEOFSIGHTTRACES 64
7530 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
7533 vec3_t boxmins, boxmaxs;
7536 dp_model_t *model = r_refdef.scene.worldmodel;
7538 if (!model || !model->brush.TraceLineOfSight)
7541 // expand the box a little
7542 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
7543 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
7544 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
7545 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
7546 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
7547 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
7549 // return true if eye is inside enlarged box
7550 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
7554 VectorCopy(eye, start);
7555 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
7556 if (model->brush.TraceLineOfSight(model, start, end))
7559 // try various random positions
7560 for (i = 0;i < numsamples;i++)
7562 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
7563 if (model->brush.TraceLineOfSight(model, start, end))
7571 static void R_View_UpdateEntityVisible (void)
7576 entity_render_t *ent;
7578 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7579 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7580 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
7581 : RENDER_EXTERIORMODEL;
7582 if (!r_drawviewmodel.integer)
7583 renderimask |= RENDER_VIEWMODEL;
7584 if (!r_drawexteriormodel.integer)
7585 renderimask |= RENDER_EXTERIORMODEL;
7586 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
7588 // worldmodel can check visibility
7589 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
7590 for (i = 0;i < r_refdef.scene.numentities;i++)
7592 ent = r_refdef.scene.entities[i];
7593 if (!(ent->flags & renderimask))
7594 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)))
7595 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))
7596 r_refdef.viewcache.entityvisible[i] = true;
7598 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
7599 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
7601 for (i = 0;i < r_refdef.scene.numentities;i++)
7603 ent = r_refdef.scene.entities[i];
7604 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
7606 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
7608 continue; // temp entities do pvs only
7609 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
7610 ent->last_trace_visibility = realtime;
7611 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
7612 r_refdef.viewcache.entityvisible[i] = 0;
7619 // no worldmodel or it can't check visibility
7620 for (i = 0;i < r_refdef.scene.numentities;i++)
7622 ent = r_refdef.scene.entities[i];
7623 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));
7628 /// only used if skyrendermasked, and normally returns false
7629 int R_DrawBrushModelsSky (void)
7632 entity_render_t *ent;
7635 for (i = 0;i < r_refdef.scene.numentities;i++)
7637 if (!r_refdef.viewcache.entityvisible[i])
7639 ent = r_refdef.scene.entities[i];
7640 if (!ent->model || !ent->model->DrawSky)
7642 ent->model->DrawSky(ent);
7648 static void R_DrawNoModel(entity_render_t *ent);
7649 static void R_DrawModels(void)
7652 entity_render_t *ent;
7654 for (i = 0;i < r_refdef.scene.numentities;i++)
7656 if (!r_refdef.viewcache.entityvisible[i])
7658 ent = r_refdef.scene.entities[i];
7659 r_refdef.stats.entities++;
7660 if (ent->model && ent->model->Draw != NULL)
7661 ent->model->Draw(ent);
7667 static void R_DrawModelsDepth(void)
7670 entity_render_t *ent;
7672 for (i = 0;i < r_refdef.scene.numentities;i++)
7674 if (!r_refdef.viewcache.entityvisible[i])
7676 ent = r_refdef.scene.entities[i];
7677 if (ent->model && ent->model->DrawDepth != NULL)
7678 ent->model->DrawDepth(ent);
7682 static void R_DrawModelsDebug(void)
7685 entity_render_t *ent;
7687 for (i = 0;i < r_refdef.scene.numentities;i++)
7689 if (!r_refdef.viewcache.entityvisible[i])
7691 ent = r_refdef.scene.entities[i];
7692 if (ent->model && ent->model->DrawDebug != NULL)
7693 ent->model->DrawDebug(ent);
7697 static void R_DrawModelsAddWaterPlanes(void)
7700 entity_render_t *ent;
7702 for (i = 0;i < r_refdef.scene.numentities;i++)
7704 if (!r_refdef.viewcache.entityvisible[i])
7706 ent = r_refdef.scene.entities[i];
7707 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
7708 ent->model->DrawAddWaterPlanes(ent);
7712 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
7714 if (r_hdr_irisadaptation.integer)
7718 vec3_t diffusenormal;
7723 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
7724 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
7725 brightness = max(0.0000001f, brightness);
7726 goal = r_hdr_irisadaptation_multiplier.value / brightness;
7727 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
7728 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
7729 current = r_hdr_irisadaptation_value.value;
7731 current = min(current + adjust, goal);
7732 else if (current > goal)
7733 current = max(current - adjust, goal);
7734 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
7735 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
7737 else if (r_hdr_irisadaptation_value.value != 1.0f)
7738 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
7741 static void R_View_SetFrustum(const int *scissor)
7744 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
7745 vec3_t forward, left, up, origin, v;
7749 // flipped x coordinates (because x points left here)
7750 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
7751 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
7753 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
7754 switch(vid.renderpath)
7756 case RENDERPATH_D3D9:
7757 case RENDERPATH_D3D10:
7758 case RENDERPATH_D3D11:
7759 case RENDERPATH_SOFT:
7760 // non-flipped y coordinates
7761 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
7762 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
7764 case RENDERPATH_GL11:
7765 case RENDERPATH_GL13:
7766 case RENDERPATH_GL20:
7767 case RENDERPATH_GLES2:
7768 // non-flipped y coordinates
7769 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
7770 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
7775 // we can't trust r_refdef.view.forward and friends in reflected scenes
7776 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
7779 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
7780 r_refdef.view.frustum[0].normal[1] = 0 - 0;
7781 r_refdef.view.frustum[0].normal[2] = -1 - 0;
7782 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
7783 r_refdef.view.frustum[1].normal[1] = 0 + 0;
7784 r_refdef.view.frustum[1].normal[2] = -1 + 0;
7785 r_refdef.view.frustum[2].normal[0] = 0 - 0;
7786 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
7787 r_refdef.view.frustum[2].normal[2] = -1 - 0;
7788 r_refdef.view.frustum[3].normal[0] = 0 + 0;
7789 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
7790 r_refdef.view.frustum[3].normal[2] = -1 + 0;
7794 zNear = r_refdef.nearclip;
7795 nudge = 1.0 - 1.0 / (1<<23);
7796 r_refdef.view.frustum[4].normal[0] = 0 - 0;
7797 r_refdef.view.frustum[4].normal[1] = 0 - 0;
7798 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
7799 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
7800 r_refdef.view.frustum[5].normal[0] = 0 + 0;
7801 r_refdef.view.frustum[5].normal[1] = 0 + 0;
7802 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
7803 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
7809 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
7810 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
7811 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
7812 r_refdef.view.frustum[0].dist = m[15] - m[12];
7814 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
7815 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
7816 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
7817 r_refdef.view.frustum[1].dist = m[15] + m[12];
7819 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
7820 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
7821 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
7822 r_refdef.view.frustum[2].dist = m[15] - m[13];
7824 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
7825 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
7826 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
7827 r_refdef.view.frustum[3].dist = m[15] + m[13];
7829 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
7830 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
7831 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
7832 r_refdef.view.frustum[4].dist = m[15] - m[14];
7834 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
7835 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
7836 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
7837 r_refdef.view.frustum[5].dist = m[15] + m[14];
7840 if (r_refdef.view.useperspective)
7842 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
7843 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]);
7844 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]);
7845 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]);
7846 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]);
7848 // then the normals from the corners relative to origin
7849 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
7850 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
7851 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
7852 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
7854 // in a NORMAL view, forward cross left == up
7855 // in a REFLECTED view, forward cross left == down
7856 // so our cross products above need to be adjusted for a left handed coordinate system
7857 CrossProduct(forward, left, v);
7858 if(DotProduct(v, up) < 0)
7860 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
7861 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
7862 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
7863 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
7866 // Leaving those out was a mistake, those were in the old code, and they
7867 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
7868 // I couldn't reproduce it after adding those normalizations. --blub
7869 VectorNormalize(r_refdef.view.frustum[0].normal);
7870 VectorNormalize(r_refdef.view.frustum[1].normal);
7871 VectorNormalize(r_refdef.view.frustum[2].normal);
7872 VectorNormalize(r_refdef.view.frustum[3].normal);
7874 // make the corners absolute
7875 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
7876 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
7877 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
7878 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
7881 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7883 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
7884 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
7885 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
7886 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
7887 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7891 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
7892 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
7893 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
7894 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
7895 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7896 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
7897 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
7898 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
7899 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
7900 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7902 r_refdef.view.numfrustumplanes = 5;
7904 if (r_refdef.view.useclipplane)
7906 r_refdef.view.numfrustumplanes = 6;
7907 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
7910 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7911 PlaneClassify(r_refdef.view.frustum + i);
7913 // LordHavoc: note to all quake engine coders, Quake had a special case
7914 // for 90 degrees which assumed a square view (wrong), so I removed it,
7915 // Quake2 has it disabled as well.
7917 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
7918 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
7919 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
7920 //PlaneClassify(&frustum[0]);
7922 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
7923 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
7924 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
7925 //PlaneClassify(&frustum[1]);
7927 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
7928 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
7929 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
7930 //PlaneClassify(&frustum[2]);
7932 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
7933 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
7934 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
7935 //PlaneClassify(&frustum[3]);
7938 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
7939 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
7940 //PlaneClassify(&frustum[4]);
7943 void R_View_UpdateWithScissor(const int *myscissor)
7945 R_Main_ResizeViewCache();
7946 R_View_SetFrustum(myscissor);
7947 R_View_WorldVisibility(r_refdef.view.useclipplane);
7948 R_View_UpdateEntityVisible();
7949 R_View_UpdateEntityLighting();
7952 void R_View_Update(void)
7954 R_Main_ResizeViewCache();
7955 R_View_SetFrustum(NULL);
7956 R_View_WorldVisibility(r_refdef.view.useclipplane);
7957 R_View_UpdateEntityVisible();
7958 R_View_UpdateEntityLighting();
7961 void R_SetupView(qboolean allowwaterclippingplane)
7963 const float *customclipplane = NULL;
7965 if (r_refdef.view.useclipplane && allowwaterclippingplane)
7967 // LordHavoc: couldn't figure out how to make this approach the
7968 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
7969 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
7970 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
7971 dist = r_refdef.view.clipplane.dist;
7972 plane[0] = r_refdef.view.clipplane.normal[0];
7973 plane[1] = r_refdef.view.clipplane.normal[1];
7974 plane[2] = r_refdef.view.clipplane.normal[2];
7976 customclipplane = plane;
7979 if (!r_refdef.view.useperspective)
7980 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);
7981 else if (vid.stencil && r_useinfinitefarclip.integer)
7982 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);
7984 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);
7985 R_SetViewport(&r_refdef.view.viewport);
7988 void R_EntityMatrix(const matrix4x4_t *matrix)
7990 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
7992 gl_modelmatrixchanged = false;
7993 gl_modelmatrix = *matrix;
7994 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
7995 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
7996 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
7997 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
7999 switch(vid.renderpath)
8001 case RENDERPATH_D3D9:
8003 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
8004 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
8007 case RENDERPATH_D3D10:
8008 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
8010 case RENDERPATH_D3D11:
8011 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
8013 case RENDERPATH_GL13:
8014 case RENDERPATH_GL11:
8015 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8017 case RENDERPATH_SOFT:
8018 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
8019 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
8021 case RENDERPATH_GL20:
8022 case RENDERPATH_GLES2:
8023 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
8024 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
8030 void R_ResetViewRendering2D(void)
8032 r_viewport_t viewport;
8035 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
8036 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);
8037 R_SetViewport(&viewport);
8038 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
8039 GL_Color(1, 1, 1, 1);
8040 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8041 GL_BlendFunc(GL_ONE, GL_ZERO);
8042 GL_ScissorTest(false);
8043 GL_DepthMask(false);
8044 GL_DepthRange(0, 1);
8045 GL_DepthTest(false);
8046 GL_DepthFunc(GL_LEQUAL);
8047 R_EntityMatrix(&identitymatrix);
8048 R_Mesh_ResetTextureState();
8049 GL_PolygonOffset(0, 0);
8050 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8051 switch(vid.renderpath)
8053 case RENDERPATH_GL11:
8054 case RENDERPATH_GL13:
8055 case RENDERPATH_GL20:
8056 case RENDERPATH_GLES2:
8057 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8059 case RENDERPATH_D3D9:
8060 case RENDERPATH_D3D10:
8061 case RENDERPATH_D3D11:
8062 case RENDERPATH_SOFT:
8065 GL_CullFace(GL_NONE);
8068 void R_ResetViewRendering3D(void)
8073 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
8074 GL_Color(1, 1, 1, 1);
8075 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8076 GL_BlendFunc(GL_ONE, GL_ZERO);
8077 GL_ScissorTest(true);
8079 GL_DepthRange(0, 1);
8081 GL_DepthFunc(GL_LEQUAL);
8082 R_EntityMatrix(&identitymatrix);
8083 R_Mesh_ResetTextureState();
8084 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8085 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8086 switch(vid.renderpath)
8088 case RENDERPATH_GL11:
8089 case RENDERPATH_GL13:
8090 case RENDERPATH_GL20:
8091 case RENDERPATH_GLES2:
8092 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8094 case RENDERPATH_D3D9:
8095 case RENDERPATH_D3D10:
8096 case RENDERPATH_D3D11:
8097 case RENDERPATH_SOFT:
8100 GL_CullFace(r_refdef.view.cullface_back);
8105 R_RenderView_UpdateViewVectors
8108 static void R_RenderView_UpdateViewVectors(void)
8110 // break apart the view matrix into vectors for various purposes
8111 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
8112 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
8113 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
8114 VectorNegate(r_refdef.view.left, r_refdef.view.right);
8115 // make an inverted copy of the view matrix for tracking sprites
8116 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
8119 void R_RenderScene(void);
8120 void R_RenderWaterPlanes(void);
8122 static void R_Water_StartFrame(void)
8125 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
8126 r_waterstate_waterplane_t *p;
8128 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
8131 switch(vid.renderpath)
8133 case RENDERPATH_GL20:
8134 case RENDERPATH_D3D9:
8135 case RENDERPATH_D3D10:
8136 case RENDERPATH_D3D11:
8137 case RENDERPATH_SOFT:
8138 case RENDERPATH_GLES2:
8140 case RENDERPATH_GL13:
8141 case RENDERPATH_GL11:
8145 // set waterwidth and waterheight to the water resolution that will be
8146 // used (often less than the screen resolution for faster rendering)
8147 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
8148 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
8150 // calculate desired texture sizes
8151 // can't use water if the card does not support the texture size
8152 if (!r_water.integer || r_showsurfaces.integer)
8153 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
8154 else if (vid.support.arb_texture_non_power_of_two)
8156 texturewidth = waterwidth;
8157 textureheight = waterheight;
8158 camerawidth = waterwidth;
8159 cameraheight = waterheight;
8163 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
8164 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
8165 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
8166 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
8169 // allocate textures as needed
8170 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
8172 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8173 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
8175 if (p->texture_refraction)
8176 R_FreeTexture(p->texture_refraction);
8177 p->texture_refraction = NULL;
8178 if (p->texture_reflection)
8179 R_FreeTexture(p->texture_reflection);
8180 p->texture_reflection = NULL;
8181 if (p->texture_camera)
8182 R_FreeTexture(p->texture_camera);
8183 p->texture_camera = NULL;
8185 memset(&r_waterstate, 0, sizeof(r_waterstate));
8186 r_waterstate.texturewidth = texturewidth;
8187 r_waterstate.textureheight = textureheight;
8188 r_waterstate.camerawidth = camerawidth;
8189 r_waterstate.cameraheight = cameraheight;
8192 if (r_waterstate.texturewidth)
8194 r_waterstate.enabled = true;
8196 // when doing a reduced render (HDR) we want to use a smaller area
8197 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
8198 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
8200 // set up variables that will be used in shader setup
8201 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8202 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8203 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8204 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8207 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8208 r_waterstate.numwaterplanes = 0;
8211 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
8213 int triangleindex, planeindex;
8219 r_waterstate_waterplane_t *p;
8220 texture_t *t = R_GetCurrentTexture(surface->texture);
8222 // just use the first triangle with a valid normal for any decisions
8223 VectorClear(normal);
8224 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
8226 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
8227 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
8228 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
8229 TriangleNormal(vert[0], vert[1], vert[2], normal);
8230 if (VectorLength2(normal) >= 0.001)
8234 VectorCopy(normal, plane.normal);
8235 VectorNormalize(plane.normal);
8236 plane.dist = DotProduct(vert[0], plane.normal);
8237 PlaneClassify(&plane);
8238 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
8240 // skip backfaces (except if nocullface is set)
8241 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
8243 VectorNegate(plane.normal, plane.normal);
8245 PlaneClassify(&plane);
8249 // find a matching plane if there is one
8250 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8251 if(p->camera_entity == t->camera_entity)
8252 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
8254 if (planeindex >= r_waterstate.maxwaterplanes)
8255 return; // nothing we can do, out of planes
8257 // if this triangle does not fit any known plane rendered this frame, add one
8258 if (planeindex >= r_waterstate.numwaterplanes)
8260 // store the new plane
8261 r_waterstate.numwaterplanes++;
8263 // clear materialflags and pvs
8264 p->materialflags = 0;
8265 p->pvsvalid = false;
8266 p->camera_entity = t->camera_entity;
8267 VectorCopy(surface->mins, p->mins);
8268 VectorCopy(surface->maxs, p->maxs);
8273 p->mins[0] = min(p->mins[0], surface->mins[0]);
8274 p->mins[1] = min(p->mins[1], surface->mins[1]);
8275 p->mins[2] = min(p->mins[2], surface->mins[2]);
8276 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
8277 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
8278 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
8280 // merge this surface's materialflags into the waterplane
8281 p->materialflags |= t->currentmaterialflags;
8282 if(!(p->materialflags & MATERIALFLAG_CAMERA))
8284 // merge this surface's PVS into the waterplane
8285 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
8286 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
8287 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
8289 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
8295 static void R_Water_ProcessPlanes(void)
8298 r_refdef_view_t originalview;
8299 r_refdef_view_t myview;
8301 r_waterstate_waterplane_t *p;
8304 originalview = r_refdef.view;
8306 // make sure enough textures are allocated
8307 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8309 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8311 if (!p->texture_refraction)
8312 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);
8313 if (!p->texture_refraction)
8316 else if (p->materialflags & MATERIALFLAG_CAMERA)
8318 if (!p->texture_camera)
8319 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);
8320 if (!p->texture_camera)
8324 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8326 if (!p->texture_reflection)
8327 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);
8328 if (!p->texture_reflection)
8334 r_refdef.view = originalview;
8335 r_refdef.view.showdebug = false;
8336 r_refdef.view.width = r_waterstate.waterwidth;
8337 r_refdef.view.height = r_waterstate.waterheight;
8338 r_refdef.view.useclipplane = true;
8339 myview = r_refdef.view;
8340 r_waterstate.renderingscene = true;
8341 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8343 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8345 r_refdef.view = myview;
8346 if(r_water_scissormode.integer)
8349 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8350 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8353 // render reflected scene and copy into texture
8354 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
8355 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
8356 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
8357 r_refdef.view.clipplane = p->plane;
8359 // reverse the cullface settings for this render
8360 r_refdef.view.cullface_front = GL_FRONT;
8361 r_refdef.view.cullface_back = GL_BACK;
8362 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
8364 r_refdef.view.usecustompvs = true;
8366 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8368 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8371 R_ResetViewRendering3D();
8372 R_ClearScreen(r_refdef.fogenabled);
8373 if(r_water_scissormode.integer & 2)
8374 R_View_UpdateWithScissor(myscissor);
8377 if(r_water_scissormode.integer & 1)
8378 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8381 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);
8384 // render the normal view scene and copy into texture
8385 // (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)
8386 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8388 r_refdef.view = myview;
8389 if(r_water_scissormode.integer)
8392 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8393 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8396 r_waterstate.renderingrefraction = true;
8398 r_refdef.view.clipplane = p->plane;
8399 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8400 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8402 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
8404 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8405 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
8406 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8407 R_RenderView_UpdateViewVectors();
8408 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8410 r_refdef.view.usecustompvs = true;
8411 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);
8415 PlaneClassify(&r_refdef.view.clipplane);
8417 R_ResetViewRendering3D();
8418 R_ClearScreen(r_refdef.fogenabled);
8419 if(r_water_scissormode.integer & 2)
8420 R_View_UpdateWithScissor(myscissor);
8423 if(r_water_scissormode.integer & 1)
8424 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8427 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);
8428 r_waterstate.renderingrefraction = false;
8430 else if (p->materialflags & MATERIALFLAG_CAMERA)
8432 r_refdef.view = myview;
8434 r_refdef.view.clipplane = p->plane;
8435 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8436 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8438 r_refdef.view.width = r_waterstate.camerawidth;
8439 r_refdef.view.height = r_waterstate.cameraheight;
8440 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
8441 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
8443 if(p->camera_entity)
8445 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8446 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8449 // note: all of the view is used for displaying... so
8450 // there is no use in scissoring
8452 // reverse the cullface settings for this render
8453 r_refdef.view.cullface_front = GL_FRONT;
8454 r_refdef.view.cullface_back = GL_BACK;
8455 // also reverse the view matrix
8456 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
8457 R_RenderView_UpdateViewVectors();
8458 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8460 r_refdef.view.usecustompvs = true;
8461 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);
8464 // camera needs no clipplane
8465 r_refdef.view.useclipplane = false;
8467 PlaneClassify(&r_refdef.view.clipplane);
8469 R_ResetViewRendering3D();
8470 R_ClearScreen(r_refdef.fogenabled);
8474 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);
8475 r_waterstate.renderingrefraction = false;
8479 r_waterstate.renderingscene = false;
8480 r_refdef.view = originalview;
8481 R_ResetViewRendering3D();
8482 R_ClearScreen(r_refdef.fogenabled);
8486 r_refdef.view = originalview;
8487 r_waterstate.renderingscene = false;
8488 Cvar_SetValueQuick(&r_water, 0);
8489 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
8493 void R_Bloom_StartFrame(void)
8495 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
8497 switch(vid.renderpath)
8499 case RENDERPATH_GL20:
8500 case RENDERPATH_D3D9:
8501 case RENDERPATH_D3D10:
8502 case RENDERPATH_D3D11:
8503 case RENDERPATH_SOFT:
8504 case RENDERPATH_GLES2:
8506 case RENDERPATH_GL13:
8507 case RENDERPATH_GL11:
8511 // set bloomwidth and bloomheight to the bloom resolution that will be
8512 // used (often less than the screen resolution for faster rendering)
8513 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
8514 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
8515 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
8516 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
8517 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
8519 // calculate desired texture sizes
8520 if (vid.support.arb_texture_non_power_of_two)
8522 screentexturewidth = r_refdef.view.width;
8523 screentextureheight = r_refdef.view.height;
8524 bloomtexturewidth = r_bloomstate.bloomwidth;
8525 bloomtextureheight = r_bloomstate.bloomheight;
8529 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
8530 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
8531 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
8532 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
8535 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))
8537 Cvar_SetValueQuick(&r_hdr, 0);
8538 Cvar_SetValueQuick(&r_bloom, 0);
8539 Cvar_SetValueQuick(&r_motionblur, 0);
8540 Cvar_SetValueQuick(&r_damageblur, 0);
8543 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)))
8544 screentexturewidth = screentextureheight = 0;
8545 if (!r_hdr.integer && !r_bloom.integer)
8546 bloomtexturewidth = bloomtextureheight = 0;
8548 // allocate textures as needed
8549 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
8551 if (r_bloomstate.texture_screen)
8552 R_FreeTexture(r_bloomstate.texture_screen);
8553 r_bloomstate.texture_screen = NULL;
8554 r_bloomstate.screentexturewidth = screentexturewidth;
8555 r_bloomstate.screentextureheight = screentextureheight;
8556 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
8557 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);
8559 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
8561 if (r_bloomstate.texture_bloom)
8562 R_FreeTexture(r_bloomstate.texture_bloom);
8563 r_bloomstate.texture_bloom = NULL;
8564 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
8565 r_bloomstate.bloomtextureheight = bloomtextureheight;
8566 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
8567 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);
8570 // when doing a reduced render (HDR) we want to use a smaller area
8571 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
8572 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
8573 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
8574 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
8575 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
8577 // set up a texcoord array for the full resolution screen image
8578 // (we have to keep this around to copy back during final render)
8579 r_bloomstate.screentexcoord2f[0] = 0;
8580 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
8581 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
8582 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
8583 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
8584 r_bloomstate.screentexcoord2f[5] = 0;
8585 r_bloomstate.screentexcoord2f[6] = 0;
8586 r_bloomstate.screentexcoord2f[7] = 0;
8588 // set up a texcoord array for the reduced resolution bloom image
8589 // (which will be additive blended over the screen image)
8590 r_bloomstate.bloomtexcoord2f[0] = 0;
8591 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8592 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8593 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8594 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8595 r_bloomstate.bloomtexcoord2f[5] = 0;
8596 r_bloomstate.bloomtexcoord2f[6] = 0;
8597 r_bloomstate.bloomtexcoord2f[7] = 0;
8599 switch(vid.renderpath)
8601 case RENDERPATH_GL11:
8602 case RENDERPATH_GL13:
8603 case RENDERPATH_GL20:
8604 case RENDERPATH_SOFT:
8605 case RENDERPATH_GLES2:
8607 case RENDERPATH_D3D9:
8608 case RENDERPATH_D3D10:
8609 case RENDERPATH_D3D11:
8612 for (i = 0;i < 4;i++)
8614 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
8615 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
8616 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
8617 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
8623 if (r_hdr.integer || r_bloom.integer)
8625 r_bloomstate.enabled = true;
8626 r_bloomstate.hdr = r_hdr.integer != 0;
8629 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);
8632 void R_Bloom_CopyBloomTexture(float colorscale)
8634 r_refdef.stats.bloom++;
8636 // scale down screen texture to the bloom texture size
8638 R_SetViewport(&r_bloomstate.viewport);
8639 GL_BlendFunc(GL_ONE, GL_ZERO);
8640 GL_Color(colorscale, colorscale, colorscale, 1);
8641 // 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...
8642 switch(vid.renderpath)
8644 case RENDERPATH_GL11:
8645 case RENDERPATH_GL13:
8646 case RENDERPATH_GL20:
8647 case RENDERPATH_SOFT:
8648 case RENDERPATH_GLES2:
8649 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8651 case RENDERPATH_D3D9:
8652 case RENDERPATH_D3D10:
8653 case RENDERPATH_D3D11:
8654 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8657 // TODO: do boxfilter scale-down in shader?
8658 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
8659 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8660 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8662 // we now have a bloom image in the framebuffer
8663 // copy it into the bloom image texture for later processing
8664 R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
8665 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8668 void R_Bloom_CopyHDRTexture(void)
8670 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);
8671 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8674 void R_Bloom_MakeTexture(void)
8677 float xoffset, yoffset, r, brighten;
8679 r_refdef.stats.bloom++;
8681 R_ResetViewRendering2D();
8683 // we have a bloom image in the framebuffer
8685 R_SetViewport(&r_bloomstate.viewport);
8687 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
8690 r = bound(0, r_bloom_colorexponent.value / x, 1);
8691 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
8693 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
8694 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
8695 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8696 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8698 // copy the vertically blurred bloom view to a texture
8699 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);
8700 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8703 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
8704 brighten = r_bloom_brighten.value;
8706 brighten *= r_hdr_range.value;
8707 brighten = sqrt(brighten);
8709 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
8710 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
8712 for (dir = 0;dir < 2;dir++)
8714 // blend on at multiple vertical offsets to achieve a vertical blur
8715 // TODO: do offset blends using GLSL
8716 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
8717 GL_BlendFunc(GL_ONE, GL_ZERO);
8718 for (x = -range;x <= range;x++)
8720 if (!dir){xoffset = 0;yoffset = x;}
8721 else {xoffset = x;yoffset = 0;}
8722 xoffset /= (float)r_bloomstate.bloomtexturewidth;
8723 yoffset /= (float)r_bloomstate.bloomtextureheight;
8724 // compute a texcoord array with the specified x and y offset
8725 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
8726 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8727 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8728 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8729 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8730 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
8731 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
8732 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
8733 // this r value looks like a 'dot' particle, fading sharply to
8734 // black at the edges
8735 // (probably not realistic but looks good enough)
8736 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
8737 //r = brighten/(range*2+1);
8738 r = brighten / (range * 2 + 1);
8740 r *= (1 - x*x/(float)(range*range));
8741 GL_Color(r, r, r, 1);
8742 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
8743 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8744 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8745 GL_BlendFunc(GL_ONE, GL_ONE);
8748 // copy the vertically blurred bloom view to a texture
8749 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);
8750 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8754 void R_HDR_RenderBloomTexture(void)
8756 int oldwidth, oldheight;
8757 float oldcolorscale;
8758 qboolean oldwaterstate;
8760 oldwaterstate = r_waterstate.enabled;
8761 oldcolorscale = r_refdef.view.colorscale;
8762 oldwidth = r_refdef.view.width;
8763 oldheight = r_refdef.view.height;
8764 r_refdef.view.width = r_bloomstate.bloomwidth;
8765 r_refdef.view.height = r_bloomstate.bloomheight;
8767 if(r_hdr.integer < 2)
8768 r_waterstate.enabled = false;
8770 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
8771 // TODO: add exposure compensation features
8772 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
8774 r_refdef.view.showdebug = false;
8775 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
8777 R_ResetViewRendering3D();
8779 R_ClearScreen(r_refdef.fogenabled);
8780 if (r_timereport_active)
8781 R_TimeReport("HDRclear");
8784 if (r_timereport_active)
8785 R_TimeReport("visibility");
8787 // only do secondary renders with HDR if r_hdr is 2 or higher
8788 r_waterstate.numwaterplanes = 0;
8789 if (r_waterstate.enabled)
8790 R_RenderWaterPlanes();
8792 r_refdef.view.showdebug = true;
8794 r_waterstate.numwaterplanes = 0;
8796 R_ResetViewRendering2D();
8798 R_Bloom_CopyHDRTexture();
8799 R_Bloom_MakeTexture();
8801 // restore the view settings
8802 r_waterstate.enabled = oldwaterstate;
8803 r_refdef.view.width = oldwidth;
8804 r_refdef.view.height = oldheight;
8805 r_refdef.view.colorscale = oldcolorscale;
8807 R_ResetViewRendering3D();
8809 R_ClearScreen(r_refdef.fogenabled);
8810 if (r_timereport_active)
8811 R_TimeReport("viewclear");
8814 static void R_BlendView(void)
8816 unsigned int permutation;
8817 float uservecs[4][4];
8819 switch (vid.renderpath)
8821 case RENDERPATH_GL20:
8822 case RENDERPATH_D3D9:
8823 case RENDERPATH_D3D10:
8824 case RENDERPATH_D3D11:
8825 case RENDERPATH_SOFT:
8826 case RENDERPATH_GLES2:
8828 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
8829 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
8830 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
8831 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
8832 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
8834 if (r_bloomstate.texture_screen)
8836 // make sure the buffer is available
8837 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
8839 R_ResetViewRendering2D();
8841 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
8843 // declare variables
8845 static float avgspeed;
8847 speed = VectorLength(cl.movement_velocity);
8849 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
8850 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
8852 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
8853 speed = bound(0, speed, 1);
8854 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
8856 // calculate values into a standard alpha
8857 cl.motionbluralpha = 1 - exp(-
8859 (r_motionblur.value * speed / 80)
8861 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
8864 max(0.0001, cl.time - cl.oldtime) // fps independent
8867 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
8868 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
8870 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
8872 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8873 GL_Color(1, 1, 1, cl.motionbluralpha);
8874 switch(vid.renderpath)
8876 case RENDERPATH_GL11:
8877 case RENDERPATH_GL13:
8878 case RENDERPATH_GL20:
8879 case RENDERPATH_SOFT:
8880 case RENDERPATH_GLES2:
8881 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8883 case RENDERPATH_D3D9:
8884 case RENDERPATH_D3D10:
8885 case RENDERPATH_D3D11:
8886 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8889 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
8890 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8891 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8895 // copy view into the screen texture
8896 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);
8897 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8899 else if (!r_bloomstate.texture_bloom)
8901 // we may still have to do view tint...
8902 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
8904 // apply a color tint to the whole view
8905 R_ResetViewRendering2D();
8906 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8907 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
8908 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8909 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8910 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8912 break; // no screen processing, no bloom, skip it
8915 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
8917 // render simple bloom effect
8918 // copy the screen and shrink it and darken it for the bloom process
8919 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
8920 // make the bloom texture
8921 R_Bloom_MakeTexture();
8924 #if _MSC_VER >= 1400
8925 #define sscanf sscanf_s
8927 memset(uservecs, 0, sizeof(uservecs));
8928 if (r_glsl_postprocess_uservec1_enable.integer)
8929 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
8930 if (r_glsl_postprocess_uservec2_enable.integer)
8931 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
8932 if (r_glsl_postprocess_uservec3_enable.integer)
8933 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
8934 if (r_glsl_postprocess_uservec4_enable.integer)
8935 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
8937 R_ResetViewRendering2D();
8938 GL_Color(1, 1, 1, 1);
8939 GL_BlendFunc(GL_ONE, GL_ZERO);
8941 switch(vid.renderpath)
8943 case RENDERPATH_GL20:
8944 case RENDERPATH_GLES2:
8945 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
8946 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
8947 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_bloomstate.texture_screen);
8948 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_bloomstate.texture_bloom );
8949 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
8950 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]);
8951 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
8952 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]);
8953 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]);
8954 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]);
8955 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]);
8956 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
8957 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
8958 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);
8960 case RENDERPATH_D3D9:
8962 // 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...
8963 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
8964 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
8965 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
8966 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
8967 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
8968 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8969 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
8970 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
8971 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
8972 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
8973 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
8974 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
8975 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
8976 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
8979 case RENDERPATH_D3D10:
8980 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
8982 case RENDERPATH_D3D11:
8983 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
8985 case RENDERPATH_SOFT:
8986 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
8987 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
8988 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
8989 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
8990 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
8991 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8992 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
8993 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
8994 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
8995 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
8996 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
8997 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
8998 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
8999 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
9004 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9005 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9007 case RENDERPATH_GL13:
9008 case RENDERPATH_GL11:
9009 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9011 // apply a color tint to the whole view
9012 R_ResetViewRendering2D();
9013 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9014 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9015 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9016 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9017 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9023 matrix4x4_t r_waterscrollmatrix;
9025 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
9027 if (r_refdef.fog_density)
9029 r_refdef.fogcolor[0] = r_refdef.fog_red;
9030 r_refdef.fogcolor[1] = r_refdef.fog_green;
9031 r_refdef.fogcolor[2] = r_refdef.fog_blue;
9033 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
9034 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
9035 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
9036 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
9040 VectorCopy(r_refdef.fogcolor, fogvec);
9041 // color.rgb *= ContrastBoost * SceneBrightness;
9042 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
9043 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
9044 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
9045 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
9050 void R_UpdateVariables(void)
9054 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
9056 r_refdef.farclip = r_farclip_base.value;
9057 if (r_refdef.scene.worldmodel)
9058 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
9059 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
9061 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
9062 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
9063 r_refdef.polygonfactor = 0;
9064 r_refdef.polygonoffset = 0;
9065 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9066 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9068 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
9069 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
9070 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
9071 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
9072 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
9073 if (FAKELIGHT_ENABLED)
9075 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
9077 if (r_showsurfaces.integer)
9079 r_refdef.scene.rtworld = false;
9080 r_refdef.scene.rtworldshadows = false;
9081 r_refdef.scene.rtdlight = false;
9082 r_refdef.scene.rtdlightshadows = false;
9083 r_refdef.lightmapintensity = 0;
9086 if (gamemode == GAME_NEHAHRA)
9088 if (gl_fogenable.integer)
9090 r_refdef.oldgl_fogenable = true;
9091 r_refdef.fog_density = gl_fogdensity.value;
9092 r_refdef.fog_red = gl_fogred.value;
9093 r_refdef.fog_green = gl_foggreen.value;
9094 r_refdef.fog_blue = gl_fogblue.value;
9095 r_refdef.fog_alpha = 1;
9096 r_refdef.fog_start = 0;
9097 r_refdef.fog_end = gl_skyclip.value;
9098 r_refdef.fog_height = 1<<30;
9099 r_refdef.fog_fadedepth = 128;
9101 else if (r_refdef.oldgl_fogenable)
9103 r_refdef.oldgl_fogenable = false;
9104 r_refdef.fog_density = 0;
9105 r_refdef.fog_red = 0;
9106 r_refdef.fog_green = 0;
9107 r_refdef.fog_blue = 0;
9108 r_refdef.fog_alpha = 0;
9109 r_refdef.fog_start = 0;
9110 r_refdef.fog_end = 0;
9111 r_refdef.fog_height = 1<<30;
9112 r_refdef.fog_fadedepth = 128;
9116 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
9117 r_refdef.fog_start = max(0, r_refdef.fog_start);
9118 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
9120 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
9122 if (r_refdef.fog_density && r_drawfog.integer)
9124 r_refdef.fogenabled = true;
9125 // this is the point where the fog reaches 0.9986 alpha, which we
9126 // consider a good enough cutoff point for the texture
9127 // (0.9986 * 256 == 255.6)
9128 if (r_fog_exp2.integer)
9129 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
9131 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
9132 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
9133 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
9134 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
9135 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
9136 R_BuildFogHeightTexture();
9137 // fog color was already set
9138 // update the fog texture
9139 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)
9140 R_BuildFogTexture();
9141 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
9142 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
9145 r_refdef.fogenabled = false;
9147 switch(vid.renderpath)
9149 case RENDERPATH_GL20:
9150 case RENDERPATH_D3D9:
9151 case RENDERPATH_D3D10:
9152 case RENDERPATH_D3D11:
9153 case RENDERPATH_SOFT:
9154 case RENDERPATH_GLES2:
9155 if(v_glslgamma.integer && !vid_gammatables_trivial)
9157 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
9159 // build GLSL gamma texture
9160 #define RAMPWIDTH 256
9161 unsigned short ramp[RAMPWIDTH * 3];
9162 unsigned char rampbgr[RAMPWIDTH][4];
9165 r_texture_gammaramps_serial = vid_gammatables_serial;
9167 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
9168 for(i = 0; i < RAMPWIDTH; ++i)
9170 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9171 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9172 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
9175 if (r_texture_gammaramps)
9177 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
9181 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
9187 // remove GLSL gamma texture
9190 case RENDERPATH_GL13:
9191 case RENDERPATH_GL11:
9196 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
9197 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
9203 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
9204 if( scenetype != r_currentscenetype ) {
9205 // store the old scenetype
9206 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
9207 r_currentscenetype = scenetype;
9208 // move in the new scene
9209 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
9218 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
9220 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
9221 if( scenetype == r_currentscenetype ) {
9222 return &r_refdef.scene;
9224 return &r_scenes_store[ scenetype ];
9233 int dpsoftrast_test;
9234 void R_RenderView(void)
9236 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
9238 dpsoftrast_test = r_test.integer;
9240 if (r_timereport_active)
9241 R_TimeReport("start");
9242 r_textureframe++; // used only by R_GetCurrentTexture
9243 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9245 if(R_CompileShader_CheckStaticParms())
9248 if (!r_drawentities.integer)
9249 r_refdef.scene.numentities = 0;
9251 R_AnimCache_ClearCache();
9252 R_FrameData_NewFrame();
9254 /* adjust for stereo display */
9255 if(R_Stereo_Active())
9257 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);
9258 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
9261 if (r_refdef.view.isoverlay)
9263 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
9264 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
9265 R_TimeReport("depthclear");
9267 r_refdef.view.showdebug = false;
9269 r_waterstate.enabled = false;
9270 r_waterstate.numwaterplanes = 0;
9274 r_refdef.view.matrix = originalmatrix;
9280 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
9282 r_refdef.view.matrix = originalmatrix;
9283 return; //Host_Error ("R_RenderView: NULL worldmodel");
9286 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
9288 R_RenderView_UpdateViewVectors();
9290 R_Shadow_UpdateWorldLightSelection();
9292 R_Bloom_StartFrame();
9293 R_Water_StartFrame();
9296 if (r_timereport_active)
9297 R_TimeReport("viewsetup");
9299 R_ResetViewRendering3D();
9301 if (r_refdef.view.clear || r_refdef.fogenabled)
9303 R_ClearScreen(r_refdef.fogenabled);
9304 if (r_timereport_active)
9305 R_TimeReport("viewclear");
9307 r_refdef.view.clear = true;
9309 // this produces a bloom texture to be used in R_BlendView() later
9310 if (r_hdr.integer && r_bloomstate.bloomwidth)
9312 R_HDR_RenderBloomTexture();
9313 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
9314 r_textureframe++; // used only by R_GetCurrentTexture
9317 r_refdef.view.showdebug = true;
9320 if (r_timereport_active)
9321 R_TimeReport("visibility");
9323 r_waterstate.numwaterplanes = 0;
9324 if (r_waterstate.enabled)
9325 R_RenderWaterPlanes();
9328 r_waterstate.numwaterplanes = 0;
9331 if (r_timereport_active)
9332 R_TimeReport("blendview");
9334 GL_Scissor(0, 0, vid.width, vid.height);
9335 GL_ScissorTest(false);
9337 r_refdef.view.matrix = originalmatrix;
9342 void R_RenderWaterPlanes(void)
9344 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
9346 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
9347 if (r_timereport_active)
9348 R_TimeReport("waterworld");
9351 // don't let sound skip if going slow
9352 if (r_refdef.scene.extraupdate)
9355 R_DrawModelsAddWaterPlanes();
9356 if (r_timereport_active)
9357 R_TimeReport("watermodels");
9359 if (r_waterstate.numwaterplanes)
9361 R_Water_ProcessPlanes();
9362 if (r_timereport_active)
9363 R_TimeReport("waterscenes");
9367 extern void R_DrawLightningBeams (void);
9368 extern void VM_CL_AddPolygonsToMeshQueue (void);
9369 extern void R_DrawPortals (void);
9370 extern cvar_t cl_locs_show;
9371 static void R_DrawLocs(void);
9372 static void R_DrawEntityBBoxes(void);
9373 static void R_DrawModelDecals(void);
9374 extern void R_DrawModelShadows(void);
9375 extern void R_DrawModelShadowMaps(void);
9376 extern cvar_t cl_decals_newsystem;
9377 extern qboolean r_shadow_usingdeferredprepass;
9378 void R_RenderScene(void)
9380 qboolean shadowmapping = false;
9382 if (r_timereport_active)
9383 R_TimeReport("beginscene");
9385 r_refdef.stats.renders++;
9389 // don't let sound skip if going slow
9390 if (r_refdef.scene.extraupdate)
9393 R_MeshQueue_BeginScene();
9397 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);
9399 if (r_timereport_active)
9400 R_TimeReport("skystartframe");
9402 if (cl.csqc_vidvars.drawworld)
9404 // don't let sound skip if going slow
9405 if (r_refdef.scene.extraupdate)
9408 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
9410 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
9411 if (r_timereport_active)
9412 R_TimeReport("worldsky");
9415 if (R_DrawBrushModelsSky() && r_timereport_active)
9416 R_TimeReport("bmodelsky");
9418 if (skyrendermasked && skyrenderlater)
9420 // we have to force off the water clipping plane while rendering sky
9424 if (r_timereport_active)
9425 R_TimeReport("sky");
9429 R_AnimCache_CacheVisibleEntities();
9430 if (r_timereport_active)
9431 R_TimeReport("animation");
9433 R_Shadow_PrepareLights();
9434 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
9435 R_Shadow_PrepareModelShadows();
9436 if (r_timereport_active)
9437 R_TimeReport("preparelights");
9439 if (R_Shadow_ShadowMappingEnabled())
9440 shadowmapping = true;
9442 if (r_shadow_usingdeferredprepass)
9443 R_Shadow_DrawPrepass();
9445 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
9447 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
9448 if (r_timereport_active)
9449 R_TimeReport("worlddepth");
9451 if (r_depthfirst.integer >= 2)
9453 R_DrawModelsDepth();
9454 if (r_timereport_active)
9455 R_TimeReport("modeldepth");
9458 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
9460 R_DrawModelShadowMaps();
9461 R_ResetViewRendering3D();
9462 // don't let sound skip if going slow
9463 if (r_refdef.scene.extraupdate)
9467 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
9469 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
9470 if (r_timereport_active)
9471 R_TimeReport("world");
9474 // don't let sound skip if going slow
9475 if (r_refdef.scene.extraupdate)
9479 if (r_timereport_active)
9480 R_TimeReport("models");
9482 // don't let sound skip if going slow
9483 if (r_refdef.scene.extraupdate)
9486 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9488 R_DrawModelShadows();
9489 R_ResetViewRendering3D();
9490 // don't let sound skip if going slow
9491 if (r_refdef.scene.extraupdate)
9495 if (!r_shadow_usingdeferredprepass)
9497 R_Shadow_DrawLights();
9498 if (r_timereport_active)
9499 R_TimeReport("rtlights");
9502 // don't let sound skip if going slow
9503 if (r_refdef.scene.extraupdate)
9506 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9508 R_DrawModelShadows();
9509 R_ResetViewRendering3D();
9510 // don't let sound skip if going slow
9511 if (r_refdef.scene.extraupdate)
9515 if (cl.csqc_vidvars.drawworld)
9517 if (cl_decals_newsystem.integer)
9519 R_DrawModelDecals();
9520 if (r_timereport_active)
9521 R_TimeReport("modeldecals");
9526 if (r_timereport_active)
9527 R_TimeReport("decals");
9531 if (r_timereport_active)
9532 R_TimeReport("particles");
9535 if (r_timereport_active)
9536 R_TimeReport("explosions");
9538 R_DrawLightningBeams();
9539 if (r_timereport_active)
9540 R_TimeReport("lightning");
9543 VM_CL_AddPolygonsToMeshQueue();
9545 if (r_refdef.view.showdebug)
9547 if (cl_locs_show.integer)
9550 if (r_timereport_active)
9551 R_TimeReport("showlocs");
9554 if (r_drawportals.integer)
9557 if (r_timereport_active)
9558 R_TimeReport("portals");
9561 if (r_showbboxes.value > 0)
9563 R_DrawEntityBBoxes();
9564 if (r_timereport_active)
9565 R_TimeReport("bboxes");
9569 R_MeshQueue_RenderTransparent();
9570 if (r_timereport_active)
9571 R_TimeReport("drawtrans");
9573 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))
9575 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
9576 if (r_timereport_active)
9577 R_TimeReport("worlddebug");
9578 R_DrawModelsDebug();
9579 if (r_timereport_active)
9580 R_TimeReport("modeldebug");
9583 if (cl.csqc_vidvars.drawworld)
9585 R_Shadow_DrawCoronas();
9586 if (r_timereport_active)
9587 R_TimeReport("coronas");
9592 GL_DepthTest(false);
9593 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
9594 GL_Color(1, 1, 1, 1);
9595 qglBegin(GL_POLYGON);
9596 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
9597 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
9598 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
9599 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
9601 qglBegin(GL_POLYGON);
9602 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]);
9603 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]);
9604 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]);
9605 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]);
9607 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
9611 // don't let sound skip if going slow
9612 if (r_refdef.scene.extraupdate)
9615 R_ResetViewRendering2D();
9618 static const unsigned short bboxelements[36] =
9628 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
9631 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
9633 RSurf_ActiveWorldEntity();
9635 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9636 GL_DepthMask(false);
9637 GL_DepthRange(0, 1);
9638 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
9639 // R_Mesh_ResetTextureState();
9641 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
9642 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
9643 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
9644 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
9645 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
9646 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
9647 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
9648 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
9649 R_FillColors(color4f, 8, cr, cg, cb, ca);
9650 if (r_refdef.fogenabled)
9652 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
9654 f1 = RSurf_FogVertex(v);
9656 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
9657 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
9658 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
9661 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
9662 R_Mesh_ResetTextureState();
9663 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9664 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
9667 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9671 prvm_edict_t *edict;
9672 prvm_prog_t *prog_save = prog;
9674 // this function draws bounding boxes of server entities
9678 GL_CullFace(GL_NONE);
9679 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9683 for (i = 0;i < numsurfaces;i++)
9685 edict = PRVM_EDICT_NUM(surfacelist[i]);
9686 switch ((int)edict->fields.server->solid)
9688 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
9689 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
9690 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
9691 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
9692 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
9693 default: Vector4Set(color, 0, 0, 0, 0.50);break;
9695 color[3] *= r_showbboxes.value;
9696 color[3] = bound(0, color[3], 1);
9697 GL_DepthTest(!r_showdisabledepthtest.integer);
9698 GL_CullFace(r_refdef.view.cullface_front);
9699 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
9705 static void R_DrawEntityBBoxes(void)
9708 prvm_edict_t *edict;
9710 prvm_prog_t *prog_save = prog;
9712 // this function draws bounding boxes of server entities
9718 for (i = 0;i < prog->num_edicts;i++)
9720 edict = PRVM_EDICT_NUM(i);
9721 if (edict->priv.server->free)
9723 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
9724 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
9726 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
9728 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
9729 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
9735 static const int nomodelelement3i[24] =
9747 static const unsigned short nomodelelement3s[24] =
9759 static const float nomodelvertex3f[6*3] =
9769 static const float nomodelcolor4f[6*4] =
9771 0.0f, 0.0f, 0.5f, 1.0f,
9772 0.0f, 0.0f, 0.5f, 1.0f,
9773 0.0f, 0.5f, 0.0f, 1.0f,
9774 0.0f, 0.5f, 0.0f, 1.0f,
9775 0.5f, 0.0f, 0.0f, 1.0f,
9776 0.5f, 0.0f, 0.0f, 1.0f
9779 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9785 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);
9787 // this is only called once per entity so numsurfaces is always 1, and
9788 // surfacelist is always {0}, so this code does not handle batches
9790 if (rsurface.ent_flags & RENDER_ADDITIVE)
9792 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
9793 GL_DepthMask(false);
9795 else if (rsurface.colormod[3] < 1)
9797 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9798 GL_DepthMask(false);
9802 GL_BlendFunc(GL_ONE, GL_ZERO);
9805 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
9806 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
9807 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
9808 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
9809 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
9810 for (i = 0, c = color4f;i < 6;i++, c += 4)
9812 c[0] *= rsurface.colormod[0];
9813 c[1] *= rsurface.colormod[1];
9814 c[2] *= rsurface.colormod[2];
9815 c[3] *= rsurface.colormod[3];
9817 if (r_refdef.fogenabled)
9819 for (i = 0, c = color4f;i < 6;i++, c += 4)
9821 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
9823 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
9824 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
9825 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
9828 // R_Mesh_ResetTextureState();
9829 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9830 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
9831 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
9834 void R_DrawNoModel(entity_render_t *ent)
9837 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
9838 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
9839 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
9841 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
9844 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
9846 vec3_t right1, right2, diff, normal;
9848 VectorSubtract (org2, org1, normal);
9850 // calculate 'right' vector for start
9851 VectorSubtract (r_refdef.view.origin, org1, diff);
9852 CrossProduct (normal, diff, right1);
9853 VectorNormalize (right1);
9855 // calculate 'right' vector for end
9856 VectorSubtract (r_refdef.view.origin, org2, diff);
9857 CrossProduct (normal, diff, right2);
9858 VectorNormalize (right2);
9860 vert[ 0] = org1[0] + width * right1[0];
9861 vert[ 1] = org1[1] + width * right1[1];
9862 vert[ 2] = org1[2] + width * right1[2];
9863 vert[ 3] = org1[0] - width * right1[0];
9864 vert[ 4] = org1[1] - width * right1[1];
9865 vert[ 5] = org1[2] - width * right1[2];
9866 vert[ 6] = org2[0] - width * right2[0];
9867 vert[ 7] = org2[1] - width * right2[1];
9868 vert[ 8] = org2[2] - width * right2[2];
9869 vert[ 9] = org2[0] + width * right2[0];
9870 vert[10] = org2[1] + width * right2[1];
9871 vert[11] = org2[2] + width * right2[2];
9874 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)
9876 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
9877 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
9878 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
9879 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
9880 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
9881 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
9882 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
9883 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
9884 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
9885 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
9886 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
9887 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
9890 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
9895 VectorSet(v, x, y, z);
9896 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
9897 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
9899 if (i == mesh->numvertices)
9901 if (mesh->numvertices < mesh->maxvertices)
9903 VectorCopy(v, vertex3f);
9904 mesh->numvertices++;
9906 return mesh->numvertices;
9912 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
9916 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
9917 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
9918 e = mesh->element3i + mesh->numtriangles * 3;
9919 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
9921 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
9922 if (mesh->numtriangles < mesh->maxtriangles)
9927 mesh->numtriangles++;
9929 element[1] = element[2];
9933 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
9937 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
9938 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
9939 e = mesh->element3i + mesh->numtriangles * 3;
9940 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
9942 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
9943 if (mesh->numtriangles < mesh->maxtriangles)
9948 mesh->numtriangles++;
9950 element[1] = element[2];
9954 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
9955 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
9957 int planenum, planenum2;
9960 mplane_t *plane, *plane2;
9962 double temppoints[2][256*3];
9963 // figure out how large a bounding box we need to properly compute this brush
9965 for (w = 0;w < numplanes;w++)
9966 maxdist = max(maxdist, fabs(planes[w].dist));
9967 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
9968 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
9969 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
9973 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
9974 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
9976 if (planenum2 == planenum)
9978 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);
9981 if (tempnumpoints < 3)
9983 // generate elements forming a triangle fan for this polygon
9984 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
9988 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)
9990 texturelayer_t *layer;
9991 layer = t->currentlayers + t->currentnumlayers++;
9993 layer->depthmask = depthmask;
9994 layer->blendfunc1 = blendfunc1;
9995 layer->blendfunc2 = blendfunc2;
9996 layer->texture = texture;
9997 layer->texmatrix = *matrix;
9998 layer->color[0] = r;
9999 layer->color[1] = g;
10000 layer->color[2] = b;
10001 layer->color[3] = a;
10004 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
10006 if(parms[0] == 0 && parms[1] == 0)
10008 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10009 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
10014 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
10017 index = parms[2] + r_refdef.scene.time * parms[3];
10018 index -= floor(index);
10019 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
10022 case Q3WAVEFUNC_NONE:
10023 case Q3WAVEFUNC_NOISE:
10024 case Q3WAVEFUNC_COUNT:
10027 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
10028 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
10029 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
10030 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
10031 case Q3WAVEFUNC_TRIANGLE:
10033 f = index - floor(index);
10036 else if (index < 2)
10038 else if (index < 3)
10044 f = parms[0] + parms[1] * f;
10045 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10046 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
10050 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
10055 matrix4x4_t matrix, temp;
10056 switch(tcmod->tcmod)
10058 case Q3TCMOD_COUNT:
10060 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10061 matrix = r_waterscrollmatrix;
10063 matrix = identitymatrix;
10065 case Q3TCMOD_ENTITYTRANSLATE:
10066 // this is used in Q3 to allow the gamecode to control texcoord
10067 // scrolling on the entity, which is not supported in darkplaces yet.
10068 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
10070 case Q3TCMOD_ROTATE:
10071 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
10072 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
10073 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
10075 case Q3TCMOD_SCALE:
10076 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
10078 case Q3TCMOD_SCROLL:
10079 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
10081 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
10082 w = (int) tcmod->parms[0];
10083 h = (int) tcmod->parms[1];
10084 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
10086 idx = (int) floor(f * w * h);
10087 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
10089 case Q3TCMOD_STRETCH:
10090 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
10091 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
10093 case Q3TCMOD_TRANSFORM:
10094 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
10095 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
10096 VectorSet(tcmat + 6, 0 , 0 , 1);
10097 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
10098 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
10100 case Q3TCMOD_TURBULENT:
10101 // this is handled in the RSurf_PrepareVertices function
10102 matrix = identitymatrix;
10106 Matrix4x4_Concat(texmatrix, &matrix, &temp);
10109 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
10111 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
10112 char name[MAX_QPATH];
10113 skinframe_t *skinframe;
10114 unsigned char pixels[296*194];
10115 strlcpy(cache->name, skinname, sizeof(cache->name));
10116 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
10117 if (developer_loading.integer)
10118 Con_Printf("loading %s\n", name);
10119 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
10120 if (!skinframe || !skinframe->base)
10123 fs_offset_t filesize;
10125 f = FS_LoadFile(name, tempmempool, true, &filesize);
10128 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
10129 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
10133 cache->skinframe = skinframe;
10136 texture_t *R_GetCurrentTexture(texture_t *t)
10139 const entity_render_t *ent = rsurface.entity;
10140 dp_model_t *model = ent->model;
10141 q3shaderinfo_layer_tcmod_t *tcmod;
10143 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
10144 return t->currentframe;
10145 t->update_lastrenderframe = r_textureframe;
10146 t->update_lastrenderentity = (void *)ent;
10148 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
10149 t->camera_entity = ent->entitynumber;
10151 t->camera_entity = 0;
10153 // switch to an alternate material if this is a q1bsp animated material
10155 texture_t *texture = t;
10156 int s = rsurface.ent_skinnum;
10157 if ((unsigned int)s >= (unsigned int)model->numskins)
10159 if (model->skinscenes)
10161 if (model->skinscenes[s].framecount > 1)
10162 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
10164 s = model->skinscenes[s].firstframe;
10167 t = t + s * model->num_surfaces;
10170 // use an alternate animation if the entity's frame is not 0,
10171 // and only if the texture has an alternate animation
10172 if (rsurface.ent_alttextures && t->anim_total[1])
10173 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
10175 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
10177 texture->currentframe = t;
10180 // update currentskinframe to be a qw skin or animation frame
10181 if (rsurface.ent_qwskin >= 0)
10183 i = rsurface.ent_qwskin;
10184 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
10186 r_qwskincache_size = cl.maxclients;
10188 Mem_Free(r_qwskincache);
10189 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
10191 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
10192 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
10193 t->currentskinframe = r_qwskincache[i].skinframe;
10194 if (t->currentskinframe == NULL)
10195 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10197 else if (t->numskinframes >= 2)
10198 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10199 if (t->backgroundnumskinframes >= 2)
10200 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
10202 t->currentmaterialflags = t->basematerialflags;
10203 t->currentalpha = rsurface.colormod[3];
10204 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
10205 t->currentalpha *= r_wateralpha.value;
10206 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
10207 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
10208 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
10209 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
10210 if (!(rsurface.ent_flags & RENDER_LIGHT))
10211 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
10212 else if (FAKELIGHT_ENABLED)
10214 // no modellight if using fakelight for the map
10216 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10218 // pick a model lighting mode
10219 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
10220 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
10222 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
10224 if (rsurface.ent_flags & RENDER_ADDITIVE)
10225 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10226 else if (t->currentalpha < 1)
10227 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10228 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
10229 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
10230 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
10231 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
10232 if (t->backgroundnumskinframes)
10233 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
10234 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
10236 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
10237 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
10240 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
10241 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
10242 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
10244 // there is no tcmod
10245 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10247 t->currenttexmatrix = r_waterscrollmatrix;
10248 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
10250 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
10252 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
10253 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
10256 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10257 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
10258 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10259 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
10261 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
10262 if (t->currentskinframe->qpixels)
10263 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
10264 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
10265 if (!t->basetexture)
10266 t->basetexture = r_texture_notexture;
10267 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
10268 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
10269 t->nmaptexture = t->currentskinframe->nmap;
10270 if (!t->nmaptexture)
10271 t->nmaptexture = r_texture_blanknormalmap;
10272 t->glosstexture = r_texture_black;
10273 t->glowtexture = t->currentskinframe->glow;
10274 t->fogtexture = t->currentskinframe->fog;
10275 t->reflectmasktexture = t->currentskinframe->reflect;
10276 if (t->backgroundnumskinframes)
10278 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
10279 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
10280 t->backgroundglosstexture = r_texture_black;
10281 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
10282 if (!t->backgroundnmaptexture)
10283 t->backgroundnmaptexture = r_texture_blanknormalmap;
10287 t->backgroundbasetexture = r_texture_white;
10288 t->backgroundnmaptexture = r_texture_blanknormalmap;
10289 t->backgroundglosstexture = r_texture_black;
10290 t->backgroundglowtexture = NULL;
10292 t->specularpower = r_shadow_glossexponent.value;
10293 // TODO: store reference values for these in the texture?
10294 t->specularscale = 0;
10295 if (r_shadow_gloss.integer > 0)
10297 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
10299 if (r_shadow_glossintensity.value > 0)
10301 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
10302 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
10303 t->specularscale = r_shadow_glossintensity.value;
10306 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
10308 t->glosstexture = r_texture_white;
10309 t->backgroundglosstexture = r_texture_white;
10310 t->specularscale = r_shadow_gloss2intensity.value;
10311 t->specularpower = r_shadow_gloss2exponent.value;
10314 t->specularscale *= t->specularscalemod;
10315 t->specularpower *= t->specularpowermod;
10317 // lightmaps mode looks bad with dlights using actual texturing, so turn
10318 // off the colormap and glossmap, but leave the normalmap on as it still
10319 // accurately represents the shading involved
10320 if (gl_lightmaps.integer)
10322 t->basetexture = r_texture_grey128;
10323 t->pantstexture = r_texture_black;
10324 t->shirttexture = r_texture_black;
10325 t->nmaptexture = r_texture_blanknormalmap;
10326 t->glosstexture = r_texture_black;
10327 t->glowtexture = NULL;
10328 t->fogtexture = NULL;
10329 t->reflectmasktexture = NULL;
10330 t->backgroundbasetexture = NULL;
10331 t->backgroundnmaptexture = r_texture_blanknormalmap;
10332 t->backgroundglosstexture = r_texture_black;
10333 t->backgroundglowtexture = NULL;
10334 t->specularscale = 0;
10335 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
10338 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
10339 VectorClear(t->dlightcolor);
10340 t->currentnumlayers = 0;
10341 if (t->currentmaterialflags & MATERIALFLAG_WALL)
10343 int blendfunc1, blendfunc2;
10344 qboolean depthmask;
10345 if (t->currentmaterialflags & MATERIALFLAG_ADD)
10347 blendfunc1 = GL_SRC_ALPHA;
10348 blendfunc2 = GL_ONE;
10350 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
10352 blendfunc1 = GL_SRC_ALPHA;
10353 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
10355 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10357 blendfunc1 = t->customblendfunc[0];
10358 blendfunc2 = t->customblendfunc[1];
10362 blendfunc1 = GL_ONE;
10363 blendfunc2 = GL_ZERO;
10365 // don't colormod evilblend textures
10366 if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
10367 VectorSet(t->lightmapcolor, 1, 1, 1);
10368 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
10369 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10371 // fullbright is not affected by r_refdef.lightmapintensity
10372 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]);
10373 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10374 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]);
10375 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10376 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]);
10380 vec3_t ambientcolor;
10382 // set the color tint used for lights affecting this surface
10383 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
10385 // q3bsp has no lightmap updates, so the lightstylevalue that
10386 // would normally be baked into the lightmap must be
10387 // applied to the color
10388 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
10389 if (model->type == mod_brushq3)
10390 colorscale *= r_refdef.scene.rtlightstylevalue[0];
10391 colorscale *= r_refdef.lightmapintensity;
10392 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
10393 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
10394 // basic lit geometry
10395 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]);
10396 // add pants/shirt if needed
10397 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10398 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]);
10399 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10400 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]);
10401 // now add ambient passes if needed
10402 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
10404 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]);
10405 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10406 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]);
10407 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10408 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]);
10411 if (t->glowtexture != NULL && !gl_lightmaps.integer)
10412 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]);
10413 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
10415 // if this is opaque use alpha blend which will darken the earlier
10418 // if this is an alpha blended material, all the earlier passes
10419 // were darkened by fog already, so we only need to add the fog
10420 // color ontop through the fog mask texture
10422 // if this is an additive blended material, all the earlier passes
10423 // were darkened by fog already, and we should not add fog color
10424 // (because the background was not darkened, there is no fog color
10425 // that was lost behind it).
10426 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]);
10430 return t->currentframe;
10433 rsurfacestate_t rsurface;
10435 void RSurf_ActiveWorldEntity(void)
10437 dp_model_t *model = r_refdef.scene.worldmodel;
10438 //if (rsurface.entity == r_refdef.scene.worldentity)
10440 rsurface.entity = r_refdef.scene.worldentity;
10441 rsurface.skeleton = NULL;
10442 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
10443 rsurface.ent_skinnum = 0;
10444 rsurface.ent_qwskin = -1;
10445 rsurface.ent_shadertime = 0;
10446 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
10447 rsurface.matrix = identitymatrix;
10448 rsurface.inversematrix = identitymatrix;
10449 rsurface.matrixscale = 1;
10450 rsurface.inversematrixscale = 1;
10451 R_EntityMatrix(&identitymatrix);
10452 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
10453 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
10454 rsurface.fograngerecip = r_refdef.fograngerecip;
10455 rsurface.fogheightfade = r_refdef.fogheightfade;
10456 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
10457 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10458 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10459 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10460 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10461 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10462 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10463 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
10464 rsurface.colormod[3] = 1;
10465 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);
10466 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10467 rsurface.frameblend[0].lerp = 1;
10468 rsurface.ent_alttextures = false;
10469 rsurface.basepolygonfactor = r_refdef.polygonfactor;
10470 rsurface.basepolygonoffset = r_refdef.polygonoffset;
10471 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
10472 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10473 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10474 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10475 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10476 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10477 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10478 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10479 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10480 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
10481 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10482 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10483 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
10484 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10485 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10486 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
10487 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10488 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10489 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
10490 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10491 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10492 rsurface.modelelement3i = model->surfmesh.data_element3i;
10493 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10494 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10495 rsurface.modelelement3s = model->surfmesh.data_element3s;
10496 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10497 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10498 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10499 rsurface.modelnumvertices = model->surfmesh.num_vertices;
10500 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10501 rsurface.modelsurfaces = model->data_surfaces;
10502 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10503 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10504 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
10505 rsurface.modelgeneratedvertex = false;
10506 rsurface.batchgeneratedvertex = false;
10507 rsurface.batchfirstvertex = 0;
10508 rsurface.batchnumvertices = 0;
10509 rsurface.batchfirsttriangle = 0;
10510 rsurface.batchnumtriangles = 0;
10511 rsurface.batchvertex3f = NULL;
10512 rsurface.batchvertex3f_vertexbuffer = NULL;
10513 rsurface.batchvertex3f_bufferoffset = 0;
10514 rsurface.batchsvector3f = NULL;
10515 rsurface.batchsvector3f_vertexbuffer = NULL;
10516 rsurface.batchsvector3f_bufferoffset = 0;
10517 rsurface.batchtvector3f = NULL;
10518 rsurface.batchtvector3f_vertexbuffer = NULL;
10519 rsurface.batchtvector3f_bufferoffset = 0;
10520 rsurface.batchnormal3f = NULL;
10521 rsurface.batchnormal3f_vertexbuffer = NULL;
10522 rsurface.batchnormal3f_bufferoffset = 0;
10523 rsurface.batchlightmapcolor4f = NULL;
10524 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10525 rsurface.batchlightmapcolor4f_bufferoffset = 0;
10526 rsurface.batchtexcoordtexture2f = NULL;
10527 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10528 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10529 rsurface.batchtexcoordlightmap2f = NULL;
10530 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10531 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10532 rsurface.batchvertexmesh = NULL;
10533 rsurface.batchvertexmeshbuffer = NULL;
10534 rsurface.batchvertex3fbuffer = NULL;
10535 rsurface.batchelement3i = NULL;
10536 rsurface.batchelement3i_indexbuffer = NULL;
10537 rsurface.batchelement3i_bufferoffset = 0;
10538 rsurface.batchelement3s = NULL;
10539 rsurface.batchelement3s_indexbuffer = NULL;
10540 rsurface.batchelement3s_bufferoffset = 0;
10541 rsurface.passcolor4f = NULL;
10542 rsurface.passcolor4f_vertexbuffer = NULL;
10543 rsurface.passcolor4f_bufferoffset = 0;
10546 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
10548 dp_model_t *model = ent->model;
10549 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
10551 rsurface.entity = (entity_render_t *)ent;
10552 rsurface.skeleton = ent->skeleton;
10553 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
10554 rsurface.ent_skinnum = ent->skinnum;
10555 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;
10556 rsurface.ent_shadertime = ent->shadertime;
10557 rsurface.ent_flags = ent->flags;
10558 rsurface.matrix = ent->matrix;
10559 rsurface.inversematrix = ent->inversematrix;
10560 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10561 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10562 R_EntityMatrix(&rsurface.matrix);
10563 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10564 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10565 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10566 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10567 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10568 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10569 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
10570 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
10571 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
10572 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
10573 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
10574 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
10575 rsurface.colormod[3] = ent->alpha;
10576 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
10577 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
10578 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
10579 rsurface.basepolygonfactor = r_refdef.polygonfactor;
10580 rsurface.basepolygonoffset = r_refdef.polygonoffset;
10581 if (ent->model->brush.submodel && !prepass)
10583 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
10584 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
10586 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
10588 if (ent->animcache_vertex3f)
10590 rsurface.modelvertex3f = ent->animcache_vertex3f;
10591 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
10592 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
10593 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
10594 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
10595 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
10596 rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
10598 else if (wanttangents)
10600 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10601 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10602 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10603 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10604 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
10605 rsurface.modelvertexmesh = NULL;
10606 rsurface.modelvertexmeshbuffer = NULL;
10607 rsurface.modelvertex3fbuffer = NULL;
10609 else if (wantnormals)
10611 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10612 rsurface.modelsvector3f = NULL;
10613 rsurface.modeltvector3f = NULL;
10614 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10615 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
10616 rsurface.modelvertexmesh = NULL;
10617 rsurface.modelvertexmeshbuffer = NULL;
10618 rsurface.modelvertex3fbuffer = NULL;
10622 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10623 rsurface.modelsvector3f = NULL;
10624 rsurface.modeltvector3f = NULL;
10625 rsurface.modelnormal3f = NULL;
10626 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
10627 rsurface.modelvertexmesh = NULL;
10628 rsurface.modelvertexmeshbuffer = NULL;
10629 rsurface.modelvertex3fbuffer = NULL;
10631 rsurface.modelvertex3f_vertexbuffer = 0;
10632 rsurface.modelvertex3f_bufferoffset = 0;
10633 rsurface.modelsvector3f_vertexbuffer = 0;
10634 rsurface.modelsvector3f_bufferoffset = 0;
10635 rsurface.modeltvector3f_vertexbuffer = 0;
10636 rsurface.modeltvector3f_bufferoffset = 0;
10637 rsurface.modelnormal3f_vertexbuffer = 0;
10638 rsurface.modelnormal3f_bufferoffset = 0;
10639 rsurface.modelgeneratedvertex = true;
10643 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
10644 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10645 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10646 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10647 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10648 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10649 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10650 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10651 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10652 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
10653 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10654 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10655 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10656 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10657 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
10658 rsurface.modelgeneratedvertex = false;
10660 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
10661 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10662 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10663 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
10664 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10665 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10666 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
10667 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10668 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10669 rsurface.modelelement3i = model->surfmesh.data_element3i;
10670 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10671 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10672 rsurface.modelelement3s = model->surfmesh.data_element3s;
10673 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10674 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10675 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10676 rsurface.modelnumvertices = model->surfmesh.num_vertices;
10677 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10678 rsurface.modelsurfaces = model->data_surfaces;
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;
10719 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)
10721 rsurface.entity = r_refdef.scene.worldentity;
10722 rsurface.skeleton = NULL;
10723 rsurface.ent_skinnum = 0;
10724 rsurface.ent_qwskin = -1;
10725 rsurface.ent_shadertime = shadertime;
10726 rsurface.ent_flags = entflags;
10727 rsurface.modelnumvertices = numvertices;
10728 rsurface.modelnumtriangles = numtriangles;
10729 rsurface.matrix = *matrix;
10730 rsurface.inversematrix = *inversematrix;
10731 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10732 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10733 R_EntityMatrix(&rsurface.matrix);
10734 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10735 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10736 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10737 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10738 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10739 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10740 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10741 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10742 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10743 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10744 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10745 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
10746 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);
10747 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10748 rsurface.frameblend[0].lerp = 1;
10749 rsurface.ent_alttextures = false;
10750 rsurface.basepolygonfactor = r_refdef.polygonfactor;
10751 rsurface.basepolygonoffset = r_refdef.polygonoffset;
10754 rsurface.modelvertex3f = (float *)vertex3f;
10755 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10756 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10757 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10759 else if (wantnormals)
10761 rsurface.modelvertex3f = (float *)vertex3f;
10762 rsurface.modelsvector3f = NULL;
10763 rsurface.modeltvector3f = NULL;
10764 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10768 rsurface.modelvertex3f = (float *)vertex3f;
10769 rsurface.modelsvector3f = NULL;
10770 rsurface.modeltvector3f = NULL;
10771 rsurface.modelnormal3f = NULL;
10773 rsurface.modelvertexmesh = NULL;
10774 rsurface.modelvertexmeshbuffer = NULL;
10775 rsurface.modelvertex3fbuffer = NULL;
10776 rsurface.modelvertex3f_vertexbuffer = 0;
10777 rsurface.modelvertex3f_bufferoffset = 0;
10778 rsurface.modelsvector3f_vertexbuffer = 0;
10779 rsurface.modelsvector3f_bufferoffset = 0;
10780 rsurface.modeltvector3f_vertexbuffer = 0;
10781 rsurface.modeltvector3f_bufferoffset = 0;
10782 rsurface.modelnormal3f_vertexbuffer = 0;
10783 rsurface.modelnormal3f_bufferoffset = 0;
10784 rsurface.modelgeneratedvertex = true;
10785 rsurface.modellightmapcolor4f = (float *)color4f;
10786 rsurface.modellightmapcolor4f_vertexbuffer = 0;
10787 rsurface.modellightmapcolor4f_bufferoffset = 0;
10788 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
10789 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
10790 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
10791 rsurface.modeltexcoordlightmap2f = NULL;
10792 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
10793 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
10794 rsurface.modelelement3i = (int *)element3i;
10795 rsurface.modelelement3i_indexbuffer = NULL;
10796 rsurface.modelelement3i_bufferoffset = 0;
10797 rsurface.modelelement3s = (unsigned short *)element3s;
10798 rsurface.modelelement3s_indexbuffer = NULL;
10799 rsurface.modelelement3s_bufferoffset = 0;
10800 rsurface.modellightmapoffsets = NULL;
10801 rsurface.modelsurfaces = NULL;
10802 rsurface.batchgeneratedvertex = false;
10803 rsurface.batchfirstvertex = 0;
10804 rsurface.batchnumvertices = 0;
10805 rsurface.batchfirsttriangle = 0;
10806 rsurface.batchnumtriangles = 0;
10807 rsurface.batchvertex3f = NULL;
10808 rsurface.batchvertex3f_vertexbuffer = NULL;
10809 rsurface.batchvertex3f_bufferoffset = 0;
10810 rsurface.batchsvector3f = NULL;
10811 rsurface.batchsvector3f_vertexbuffer = NULL;
10812 rsurface.batchsvector3f_bufferoffset = 0;
10813 rsurface.batchtvector3f = NULL;
10814 rsurface.batchtvector3f_vertexbuffer = NULL;
10815 rsurface.batchtvector3f_bufferoffset = 0;
10816 rsurface.batchnormal3f = NULL;
10817 rsurface.batchnormal3f_vertexbuffer = NULL;
10818 rsurface.batchnormal3f_bufferoffset = 0;
10819 rsurface.batchlightmapcolor4f = NULL;
10820 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10821 rsurface.batchlightmapcolor4f_bufferoffset = 0;
10822 rsurface.batchtexcoordtexture2f = NULL;
10823 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10824 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10825 rsurface.batchtexcoordlightmap2f = NULL;
10826 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10827 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10828 rsurface.batchvertexmesh = NULL;
10829 rsurface.batchvertexmeshbuffer = NULL;
10830 rsurface.batchvertex3fbuffer = NULL;
10831 rsurface.batchelement3i = NULL;
10832 rsurface.batchelement3i_indexbuffer = NULL;
10833 rsurface.batchelement3i_bufferoffset = 0;
10834 rsurface.batchelement3s = NULL;
10835 rsurface.batchelement3s_indexbuffer = NULL;
10836 rsurface.batchelement3s_bufferoffset = 0;
10837 rsurface.passcolor4f = NULL;
10838 rsurface.passcolor4f_vertexbuffer = NULL;
10839 rsurface.passcolor4f_bufferoffset = 0;
10841 if (rsurface.modelnumvertices && rsurface.modelelement3i)
10843 if ((wantnormals || wanttangents) && !normal3f)
10845 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10846 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
10848 if (wanttangents && !svector3f)
10850 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10851 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10852 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
10857 float RSurf_FogPoint(const float *v)
10859 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
10860 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
10861 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
10862 float FogHeightFade = r_refdef.fogheightfade;
10864 unsigned int fogmasktableindex;
10865 if (r_refdef.fogplaneviewabove)
10866 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
10868 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
10869 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
10870 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
10873 float RSurf_FogVertex(const float *v)
10875 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
10876 float FogPlaneViewDist = rsurface.fogplaneviewdist;
10877 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
10878 float FogHeightFade = rsurface.fogheightfade;
10880 unsigned int fogmasktableindex;
10881 if (r_refdef.fogplaneviewabove)
10882 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
10884 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
10885 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
10886 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
10889 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
10892 for (i = 0;i < numelements;i++)
10893 outelement3i[i] = inelement3i[i] + adjust;
10896 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
10897 extern cvar_t gl_vbo;
10898 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
10906 int surfacefirsttriangle;
10907 int surfacenumtriangles;
10908 int surfacefirstvertex;
10909 int surfaceendvertex;
10910 int surfacenumvertices;
10911 int batchnumvertices;
10912 int batchnumtriangles;
10916 qboolean dynamicvertex;
10920 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
10921 float waveparms[4];
10922 q3shaderinfo_deform_t *deform;
10923 const msurface_t *surface, *firstsurface;
10924 r_vertexmesh_t *vertexmesh;
10925 if (!texturenumsurfaces)
10927 // find vertex range of this surface batch
10929 firstsurface = texturesurfacelist[0];
10930 firsttriangle = firstsurface->num_firsttriangle;
10931 batchnumvertices = 0;
10932 batchnumtriangles = 0;
10933 firstvertex = endvertex = firstsurface->num_firstvertex;
10934 for (i = 0;i < texturenumsurfaces;i++)
10936 surface = texturesurfacelist[i];
10937 if (surface != firstsurface + i)
10939 surfacefirstvertex = surface->num_firstvertex;
10940 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
10941 surfacenumvertices = surface->num_vertices;
10942 surfacenumtriangles = surface->num_triangles;
10943 if (firstvertex > surfacefirstvertex)
10944 firstvertex = surfacefirstvertex;
10945 if (endvertex < surfaceendvertex)
10946 endvertex = surfaceendvertex;
10947 batchnumvertices += surfacenumvertices;
10948 batchnumtriangles += surfacenumtriangles;
10951 // we now know the vertex range used, and if there are any gaps in it
10952 rsurface.batchfirstvertex = firstvertex;
10953 rsurface.batchnumvertices = endvertex - firstvertex;
10954 rsurface.batchfirsttriangle = firsttriangle;
10955 rsurface.batchnumtriangles = batchnumtriangles;
10957 // this variable holds flags for which properties have been updated that
10958 // may require regenerating vertexmesh array...
10961 // check if any dynamic vertex processing must occur
10962 dynamicvertex = false;
10964 // if there is a chance of animated vertex colors, it's a dynamic batch
10965 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
10967 dynamicvertex = true;
10968 batchneed |= BATCHNEED_NOGAPS;
10969 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
10972 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
10974 switch (deform->deform)
10977 case Q3DEFORM_PROJECTIONSHADOW:
10978 case Q3DEFORM_TEXT0:
10979 case Q3DEFORM_TEXT1:
10980 case Q3DEFORM_TEXT2:
10981 case Q3DEFORM_TEXT3:
10982 case Q3DEFORM_TEXT4:
10983 case Q3DEFORM_TEXT5:
10984 case Q3DEFORM_TEXT6:
10985 case Q3DEFORM_TEXT7:
10986 case Q3DEFORM_NONE:
10988 case Q3DEFORM_AUTOSPRITE:
10989 dynamicvertex = true;
10990 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10991 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10993 case Q3DEFORM_AUTOSPRITE2:
10994 dynamicvertex = true;
10995 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10996 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10998 case Q3DEFORM_NORMAL:
10999 dynamicvertex = true;
11000 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11001 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11003 case Q3DEFORM_WAVE:
11004 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11005 break; // if wavefunc is a nop, ignore this transform
11006 dynamicvertex = true;
11007 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11008 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11010 case Q3DEFORM_BULGE:
11011 dynamicvertex = true;
11012 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11013 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11015 case Q3DEFORM_MOVE:
11016 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11017 break; // if wavefunc is a nop, ignore this transform
11018 dynamicvertex = true;
11019 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11020 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
11024 switch(rsurface.texture->tcgen.tcgen)
11027 case Q3TCGEN_TEXTURE:
11029 case Q3TCGEN_LIGHTMAP:
11030 dynamicvertex = true;
11031 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
11032 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
11034 case Q3TCGEN_VECTOR:
11035 dynamicvertex = true;
11036 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11037 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11039 case Q3TCGEN_ENVIRONMENT:
11040 dynamicvertex = true;
11041 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
11042 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11045 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11047 dynamicvertex = true;
11048 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11049 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11052 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11054 dynamicvertex = true;
11055 batchneed |= BATCHNEED_NOGAPS;
11056 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
11059 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
11061 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
11062 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
11063 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
11064 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
11065 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
11066 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
11067 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
11070 // when the model data has no vertex buffer (dynamic mesh), we need to
11072 if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
11073 batchneed |= BATCHNEED_NOGAPS;
11075 // if needsupdate, we have to do a dynamic vertex batch for sure
11076 if (needsupdate & batchneed)
11077 dynamicvertex = true;
11079 // see if we need to build vertexmesh from arrays
11080 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11081 dynamicvertex = true;
11083 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
11084 // also some drivers strongly dislike firstvertex
11085 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
11086 dynamicvertex = true;
11088 rsurface.batchvertex3f = rsurface.modelvertex3f;
11089 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
11090 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
11091 rsurface.batchsvector3f = rsurface.modelsvector3f;
11092 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
11093 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
11094 rsurface.batchtvector3f = rsurface.modeltvector3f;
11095 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
11096 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
11097 rsurface.batchnormal3f = rsurface.modelnormal3f;
11098 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
11099 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
11100 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
11101 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
11102 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
11103 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
11104 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
11105 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
11106 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
11107 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
11108 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
11109 rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
11110 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
11111 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
11112 rsurface.batchelement3i = rsurface.modelelement3i;
11113 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
11114 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
11115 rsurface.batchelement3s = rsurface.modelelement3s;
11116 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
11117 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
11119 // if any dynamic vertex processing has to occur in software, we copy the
11120 // entire surface list together before processing to rebase the vertices
11121 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
11123 // if any gaps exist and we do not have a static vertex buffer, we have to
11124 // copy the surface list together to avoid wasting upload bandwidth on the
11125 // vertices in the gaps.
11127 // if gaps exist and we have a static vertex buffer, we still have to
11128 // combine the index buffer ranges into one dynamic index buffer.
11130 // in all cases we end up with data that can be drawn in one call.
11132 if (!dynamicvertex)
11134 // static vertex data, just set pointers...
11135 rsurface.batchgeneratedvertex = false;
11136 // if there are gaps, we want to build a combined index buffer,
11137 // otherwise use the original static buffer with an appropriate offset
11140 // build a new triangle elements array for this batch
11141 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
11142 rsurface.batchfirsttriangle = 0;
11144 for (i = 0;i < texturenumsurfaces;i++)
11146 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11147 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11148 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
11149 numtriangles += surfacenumtriangles;
11151 rsurface.batchelement3i_indexbuffer = NULL;
11152 rsurface.batchelement3i_bufferoffset = 0;
11153 rsurface.batchelement3s = NULL;
11154 rsurface.batchelement3s_indexbuffer = NULL;
11155 rsurface.batchelement3s_bufferoffset = 0;
11156 if (endvertex <= 65536)
11158 // make a 16bit (unsigned short) index array if possible
11159 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
11160 for (i = 0;i < numtriangles*3;i++)
11161 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
11167 // something needs software processing, do it for real...
11168 // we only directly handle separate array data in this case and then
11169 // generate interleaved data if needed...
11170 rsurface.batchgeneratedvertex = true;
11172 // now copy the vertex data into a combined array and make an index array
11173 // (this is what Quake3 does all the time)
11174 //if (gaps || rsurface.batchfirstvertex)
11176 rsurface.batchvertex3fbuffer = NULL;
11177 rsurface.batchvertexmesh = NULL;
11178 rsurface.batchvertexmeshbuffer = NULL;
11179 rsurface.batchvertex3f = NULL;
11180 rsurface.batchvertex3f_vertexbuffer = NULL;
11181 rsurface.batchvertex3f_bufferoffset = 0;
11182 rsurface.batchsvector3f = NULL;
11183 rsurface.batchsvector3f_vertexbuffer = NULL;
11184 rsurface.batchsvector3f_bufferoffset = 0;
11185 rsurface.batchtvector3f = NULL;
11186 rsurface.batchtvector3f_vertexbuffer = NULL;
11187 rsurface.batchtvector3f_bufferoffset = 0;
11188 rsurface.batchnormal3f = NULL;
11189 rsurface.batchnormal3f_vertexbuffer = NULL;
11190 rsurface.batchnormal3f_bufferoffset = 0;
11191 rsurface.batchlightmapcolor4f = NULL;
11192 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11193 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11194 rsurface.batchtexcoordtexture2f = NULL;
11195 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11196 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11197 rsurface.batchtexcoordlightmap2f = NULL;
11198 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11199 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11200 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
11201 rsurface.batchelement3i_indexbuffer = NULL;
11202 rsurface.batchelement3i_bufferoffset = 0;
11203 rsurface.batchelement3s = NULL;
11204 rsurface.batchelement3s_indexbuffer = NULL;
11205 rsurface.batchelement3s_bufferoffset = 0;
11206 // we'll only be setting up certain arrays as needed
11207 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11208 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
11209 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11210 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11211 if (batchneed & BATCHNEED_ARRAY_NORMAL)
11212 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11213 if (batchneed & BATCHNEED_ARRAY_VECTOR)
11215 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11216 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11218 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
11219 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
11220 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
11221 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11222 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
11223 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11226 for (i = 0;i < texturenumsurfaces;i++)
11228 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
11229 surfacenumvertices = texturesurfacelist[i]->num_vertices;
11230 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11231 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11232 // copy only the data requested
11233 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
11234 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
11235 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
11237 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11238 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11239 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
11240 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11241 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
11243 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11244 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11246 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
11247 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
11248 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
11249 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11250 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
11251 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11253 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
11254 numvertices += surfacenumvertices;
11255 numtriangles += surfacenumtriangles;
11258 // generate a 16bit index array as well if possible
11259 // (in general, dynamic batches fit)
11260 if (numvertices <= 65536)
11262 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
11263 for (i = 0;i < numtriangles*3;i++)
11264 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
11267 // since we've copied everything, the batch now starts at 0
11268 rsurface.batchfirstvertex = 0;
11269 rsurface.batchnumvertices = batchnumvertices;
11270 rsurface.batchfirsttriangle = 0;
11271 rsurface.batchnumtriangles = batchnumtriangles;
11274 // q1bsp surfaces rendered in vertex color mode have to have colors
11275 // calculated based on lightstyles
11276 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11278 // generate color arrays for the surfaces in this list
11282 const int *offsets;
11283 const unsigned char *lm;
11284 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
11285 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11286 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11288 for (i = 0;i < texturenumsurfaces;i++)
11290 surface = texturesurfacelist[i];
11291 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
11292 surfacenumvertices = surface->num_vertices;
11293 if (surface->lightmapinfo->samples)
11295 for (j = 0;j < surfacenumvertices;j++)
11297 lm = surface->lightmapinfo->samples + offsets[j];
11298 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
11299 VectorScale(lm, scale, c);
11300 if (surface->lightmapinfo->styles[1] != 255)
11302 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
11304 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
11305 VectorMA(c, scale, lm, c);
11306 if (surface->lightmapinfo->styles[2] != 255)
11309 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
11310 VectorMA(c, scale, lm, c);
11311 if (surface->lightmapinfo->styles[3] != 255)
11314 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
11315 VectorMA(c, scale, lm, c);
11322 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);
11328 for (j = 0;j < surfacenumvertices;j++)
11330 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
11337 // if vertices are deformed (sprite flares and things in maps, possibly
11338 // water waves, bulges and other deformations), modify the copied vertices
11340 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11342 switch (deform->deform)
11345 case Q3DEFORM_PROJECTIONSHADOW:
11346 case Q3DEFORM_TEXT0:
11347 case Q3DEFORM_TEXT1:
11348 case Q3DEFORM_TEXT2:
11349 case Q3DEFORM_TEXT3:
11350 case Q3DEFORM_TEXT4:
11351 case Q3DEFORM_TEXT5:
11352 case Q3DEFORM_TEXT6:
11353 case Q3DEFORM_TEXT7:
11354 case Q3DEFORM_NONE:
11356 case Q3DEFORM_AUTOSPRITE:
11357 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11358 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11359 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11360 VectorNormalize(newforward);
11361 VectorNormalize(newright);
11362 VectorNormalize(newup);
11363 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11364 // rsurface.batchvertex3f_vertexbuffer = NULL;
11365 // rsurface.batchvertex3f_bufferoffset = 0;
11366 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
11367 // rsurface.batchsvector3f_vertexbuffer = NULL;
11368 // rsurface.batchsvector3f_bufferoffset = 0;
11369 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
11370 // rsurface.batchtvector3f_vertexbuffer = NULL;
11371 // rsurface.batchtvector3f_bufferoffset = 0;
11372 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
11373 // rsurface.batchnormal3f_vertexbuffer = NULL;
11374 // rsurface.batchnormal3f_bufferoffset = 0;
11375 // a single autosprite surface can contain multiple sprites...
11376 for (j = 0;j < batchnumvertices - 3;j += 4)
11378 VectorClear(center);
11379 for (i = 0;i < 4;i++)
11380 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11381 VectorScale(center, 0.25f, center);
11382 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
11383 VectorCopy(rsurface.batchsvector3f + 3*j, right);
11384 VectorCopy(rsurface.batchtvector3f + 3*j, up);
11385 for (i = 0;i < 4;i++)
11387 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
11388 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
11391 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
11392 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11393 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);
11395 case Q3DEFORM_AUTOSPRITE2:
11396 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11397 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11398 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11399 VectorNormalize(newforward);
11400 VectorNormalize(newright);
11401 VectorNormalize(newup);
11402 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11403 // rsurface.batchvertex3f_vertexbuffer = NULL;
11404 // rsurface.batchvertex3f_bufferoffset = 0;
11406 const float *v1, *v2;
11416 memset(shortest, 0, sizeof(shortest));
11417 // a single autosprite surface can contain multiple sprites...
11418 for (j = 0;j < batchnumvertices - 3;j += 4)
11420 VectorClear(center);
11421 for (i = 0;i < 4;i++)
11422 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11423 VectorScale(center, 0.25f, center);
11424 // find the two shortest edges, then use them to define the
11425 // axis vectors for rotating around the central axis
11426 for (i = 0;i < 6;i++)
11428 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
11429 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
11430 l = VectorDistance2(v1, v2);
11431 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
11432 if (v1[2] != v2[2])
11433 l += (1.0f / 1024.0f);
11434 if (shortest[0].length2 > l || i == 0)
11436 shortest[1] = shortest[0];
11437 shortest[0].length2 = l;
11438 shortest[0].v1 = v1;
11439 shortest[0].v2 = v2;
11441 else if (shortest[1].length2 > l || i == 1)
11443 shortest[1].length2 = l;
11444 shortest[1].v1 = v1;
11445 shortest[1].v2 = v2;
11448 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
11449 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
11450 // this calculates the right vector from the shortest edge
11451 // and the up vector from the edge midpoints
11452 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
11453 VectorNormalize(right);
11454 VectorSubtract(end, start, up);
11455 VectorNormalize(up);
11456 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
11457 VectorSubtract(rsurface.localvieworigin, center, forward);
11458 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
11459 VectorNegate(forward, forward);
11460 VectorReflect(forward, 0, up, forward);
11461 VectorNormalize(forward);
11462 CrossProduct(up, forward, newright);
11463 VectorNormalize(newright);
11464 // rotate the quad around the up axis vector, this is made
11465 // especially easy by the fact we know the quad is flat,
11466 // so we only have to subtract the center position and
11467 // measure distance along the right vector, and then
11468 // multiply that by the newright vector and add back the
11470 // we also need to subtract the old position to undo the
11471 // displacement from the center, which we do with a
11472 // DotProduct, the subtraction/addition of center is also
11473 // optimized into DotProducts here
11474 l = DotProduct(right, center);
11475 for (i = 0;i < 4;i++)
11477 v1 = rsurface.batchvertex3f + 3*(j+i);
11478 f = DotProduct(right, v1) - l;
11479 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
11483 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
11485 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11486 // rsurface.batchnormal3f_vertexbuffer = NULL;
11487 // rsurface.batchnormal3f_bufferoffset = 0;
11488 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11490 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11492 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11493 // rsurface.batchsvector3f_vertexbuffer = NULL;
11494 // rsurface.batchsvector3f_bufferoffset = 0;
11495 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11496 // rsurface.batchtvector3f_vertexbuffer = NULL;
11497 // rsurface.batchtvector3f_bufferoffset = 0;
11498 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);
11501 case Q3DEFORM_NORMAL:
11502 // deform the normals to make reflections wavey
11503 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
11504 rsurface.batchnormal3f_vertexbuffer = NULL;
11505 rsurface.batchnormal3f_bufferoffset = 0;
11506 for (j = 0;j < batchnumvertices;j++)
11509 float *normal = rsurface.batchnormal3f + 3*j;
11510 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
11511 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
11512 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]);
11513 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]);
11514 VectorNormalize(normal);
11516 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11518 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11519 // rsurface.batchsvector3f_vertexbuffer = NULL;
11520 // rsurface.batchsvector3f_bufferoffset = 0;
11521 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11522 // rsurface.batchtvector3f_vertexbuffer = NULL;
11523 // rsurface.batchtvector3f_bufferoffset = 0;
11524 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);
11527 case Q3DEFORM_WAVE:
11528 // deform vertex array to make wavey water and flags and such
11529 waveparms[0] = deform->waveparms[0];
11530 waveparms[1] = deform->waveparms[1];
11531 waveparms[2] = deform->waveparms[2];
11532 waveparms[3] = deform->waveparms[3];
11533 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
11534 break; // if wavefunc is a nop, don't make a dynamic vertex array
11535 // this is how a divisor of vertex influence on deformation
11536 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
11537 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11538 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11539 // rsurface.batchvertex3f_vertexbuffer = NULL;
11540 // rsurface.batchvertex3f_bufferoffset = 0;
11541 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
11542 // rsurface.batchnormal3f_vertexbuffer = NULL;
11543 // rsurface.batchnormal3f_bufferoffset = 0;
11544 for (j = 0;j < batchnumvertices;j++)
11546 // if the wavefunc depends on time, evaluate it per-vertex
11549 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
11550 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11552 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
11554 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
11555 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11556 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11558 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11559 // rsurface.batchsvector3f_vertexbuffer = NULL;
11560 // rsurface.batchsvector3f_bufferoffset = 0;
11561 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11562 // rsurface.batchtvector3f_vertexbuffer = NULL;
11563 // rsurface.batchtvector3f_bufferoffset = 0;
11564 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);
11567 case Q3DEFORM_BULGE:
11568 // deform vertex array to make the surface have moving bulges
11569 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11570 // rsurface.batchvertex3f_vertexbuffer = NULL;
11571 // rsurface.batchvertex3f_bufferoffset = 0;
11572 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
11573 // rsurface.batchnormal3f_vertexbuffer = NULL;
11574 // rsurface.batchnormal3f_bufferoffset = 0;
11575 for (j = 0;j < batchnumvertices;j++)
11577 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
11578 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
11580 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
11581 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11582 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11584 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11585 // rsurface.batchsvector3f_vertexbuffer = NULL;
11586 // rsurface.batchsvector3f_bufferoffset = 0;
11587 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11588 // rsurface.batchtvector3f_vertexbuffer = NULL;
11589 // rsurface.batchtvector3f_bufferoffset = 0;
11590 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);
11593 case Q3DEFORM_MOVE:
11594 // deform vertex array
11595 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11596 break; // if wavefunc is a nop, don't make a dynamic vertex array
11597 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
11598 VectorScale(deform->parms, scale, waveparms);
11599 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11600 // rsurface.batchvertex3f_vertexbuffer = NULL;
11601 // rsurface.batchvertex3f_bufferoffset = 0;
11602 for (j = 0;j < batchnumvertices;j++)
11603 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
11608 // generate texcoords based on the chosen texcoord source
11609 switch(rsurface.texture->tcgen.tcgen)
11612 case Q3TCGEN_TEXTURE:
11614 case Q3TCGEN_LIGHTMAP:
11615 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11616 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11617 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11618 if (rsurface.batchtexcoordlightmap2f)
11619 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
11621 case Q3TCGEN_VECTOR:
11622 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11623 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11624 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11625 for (j = 0;j < batchnumvertices;j++)
11627 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
11628 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
11631 case Q3TCGEN_ENVIRONMENT:
11632 // make environment reflections using a spheremap
11633 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11634 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11635 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11636 for (j = 0;j < batchnumvertices;j++)
11638 // identical to Q3A's method, but executed in worldspace so
11639 // carried models can be shiny too
11641 float viewer[3], d, reflected[3], worldreflected[3];
11643 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
11644 // VectorNormalize(viewer);
11646 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
11648 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
11649 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
11650 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
11651 // note: this is proportinal to viewer, so we can normalize later
11653 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
11654 VectorNormalize(worldreflected);
11656 // note: this sphere map only uses world x and z!
11657 // so positive and negative y will LOOK THE SAME.
11658 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
11659 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
11663 // the only tcmod that needs software vertex processing is turbulent, so
11664 // check for it here and apply the changes if needed
11665 // and we only support that as the first one
11666 // (handling a mixture of turbulent and other tcmods would be problematic
11667 // without punting it entirely to a software path)
11668 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11670 amplitude = rsurface.texture->tcmods[0].parms[1];
11671 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
11672 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11673 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11674 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11675 for (j = 0;j < batchnumvertices;j++)
11677 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);
11678 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
11682 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11684 // convert the modified arrays to vertex structs
11685 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
11686 // rsurface.batchvertexmeshbuffer = NULL;
11687 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
11688 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11689 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
11690 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
11691 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11692 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
11693 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
11695 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11697 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
11698 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
11701 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
11702 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11703 Vector4Scale(rsurface.batchlightmapcolor4f + 4*j, 255.0f, vertexmesh->color4ub);
11704 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
11705 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11706 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
11707 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
11708 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11709 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
11713 void RSurf_DrawBatch(void)
11715 // sometimes a zero triangle surface (usually a degenerate patch) makes it
11716 // through the pipeline, killing it earlier in the pipeline would have
11717 // per-surface overhead rather than per-batch overhead, so it's best to
11718 // reject it here, before it hits glDraw.
11719 if (rsurface.batchnumtriangles == 0)
11722 // batch debugging code
11723 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
11729 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
11730 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
11733 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
11735 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
11737 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
11738 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);
11745 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);
11748 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
11750 // pick the closest matching water plane
11751 int planeindex, vertexindex, bestplaneindex = -1;
11755 r_waterstate_waterplane_t *p;
11756 qboolean prepared = false;
11758 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
11760 if(p->camera_entity != rsurface.texture->camera_entity)
11765 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11767 if(rsurface.batchnumvertices == 0)
11770 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
11772 Matrix4x4_Transform(&rsurface.matrix, v, vert);
11773 d += fabs(PlaneDiff(vert, &p->plane));
11775 if (bestd > d || bestplaneindex < 0)
11778 bestplaneindex = planeindex;
11781 return bestplaneindex;
11782 // NOTE: this MAY return a totally unrelated water plane; we can ignore
11783 // this situation though, as it might be better to render single larger
11784 // batches with useless stuff (backface culled for example) than to
11785 // render multiple smaller batches
11788 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
11791 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11792 rsurface.passcolor4f_vertexbuffer = 0;
11793 rsurface.passcolor4f_bufferoffset = 0;
11794 for (i = 0;i < rsurface.batchnumvertices;i++)
11795 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
11798 static void RSurf_DrawBatch_GL11_ApplyFog(void)
11805 if (rsurface.passcolor4f)
11807 // generate color arrays
11808 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
11809 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11810 rsurface.passcolor4f_vertexbuffer = 0;
11811 rsurface.passcolor4f_bufferoffset = 0;
11812 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)
11814 f = RSurf_FogVertex(v);
11823 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11824 rsurface.passcolor4f_vertexbuffer = 0;
11825 rsurface.passcolor4f_bufferoffset = 0;
11826 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
11828 f = RSurf_FogVertex(v);
11837 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
11844 if (!rsurface.passcolor4f)
11846 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
11847 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11848 rsurface.passcolor4f_vertexbuffer = 0;
11849 rsurface.passcolor4f_bufferoffset = 0;
11850 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)
11852 f = RSurf_FogVertex(v);
11853 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
11854 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
11855 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
11860 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
11865 if (!rsurface.passcolor4f)
11867 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
11868 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11869 rsurface.passcolor4f_vertexbuffer = 0;
11870 rsurface.passcolor4f_bufferoffset = 0;
11871 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
11880 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
11885 if (!rsurface.passcolor4f)
11887 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
11888 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11889 rsurface.passcolor4f_vertexbuffer = 0;
11890 rsurface.passcolor4f_bufferoffset = 0;
11891 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
11893 c2[0] = c[0] + r_refdef.scene.ambient;
11894 c2[1] = c[1] + r_refdef.scene.ambient;
11895 c2[2] = c[2] + r_refdef.scene.ambient;
11900 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11903 rsurface.passcolor4f = NULL;
11904 rsurface.passcolor4f_vertexbuffer = 0;
11905 rsurface.passcolor4f_bufferoffset = 0;
11906 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
11907 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11908 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11909 GL_Color(r, g, b, a);
11910 R_Mesh_TexBind(0, rsurface.lightmaptexture);
11914 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11916 // TODO: optimize applyfog && applycolor case
11917 // just apply fog if necessary, and tint the fog color array if necessary
11918 rsurface.passcolor4f = NULL;
11919 rsurface.passcolor4f_vertexbuffer = 0;
11920 rsurface.passcolor4f_bufferoffset = 0;
11921 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
11922 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11923 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11924 GL_Color(r, g, b, a);
11928 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11931 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
11932 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
11933 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
11934 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
11935 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11936 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11937 GL_Color(r, g, b, a);
11941 static void RSurf_DrawBatch_GL11_ClampColor(void)
11946 if (!rsurface.passcolor4f)
11948 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
11950 c2[0] = bound(0.0f, c1[0], 1.0f);
11951 c2[1] = bound(0.0f, c1[1], 1.0f);
11952 c2[2] = bound(0.0f, c1[2], 1.0f);
11953 c2[3] = bound(0.0f, c1[3], 1.0f);
11957 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
11967 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11968 rsurface.passcolor4f_vertexbuffer = 0;
11969 rsurface.passcolor4f_bufferoffset = 0;
11970 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)
11972 f = -DotProduct(r_refdef.view.forward, n);
11974 f = f * 0.85 + 0.15; // work around so stuff won't get black
11975 f *= r_refdef.lightmapintensity;
11976 Vector4Set(c, f, f, f, 1);
11980 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11982 RSurf_DrawBatch_GL11_ApplyFakeLight();
11983 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
11984 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11985 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11986 GL_Color(r, g, b, a);
11990 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
11998 vec3_t ambientcolor;
11999 vec3_t diffusecolor;
12003 VectorCopy(rsurface.modellight_lightdir, lightdir);
12004 f = 0.5f * r_refdef.lightmapintensity;
12005 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
12006 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
12007 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
12008 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
12009 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
12010 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
12012 if (VectorLength2(diffusecolor) > 0)
12014 // q3-style directional shading
12015 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12016 rsurface.passcolor4f_vertexbuffer = 0;
12017 rsurface.passcolor4f_bufferoffset = 0;
12018 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)
12020 if ((f = DotProduct(n, lightdir)) > 0)
12021 VectorMA(ambientcolor, f, diffusecolor, c);
12023 VectorCopy(ambientcolor, c);
12030 *applycolor = false;
12034 *r = ambientcolor[0];
12035 *g = ambientcolor[1];
12036 *b = ambientcolor[2];
12037 rsurface.passcolor4f = NULL;
12038 rsurface.passcolor4f_vertexbuffer = 0;
12039 rsurface.passcolor4f_bufferoffset = 0;
12043 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12045 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
12046 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
12047 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12048 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12049 GL_Color(r, g, b, a);
12053 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
12059 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
12061 f = 1 - RSurf_FogVertex(v);
12069 void RSurf_SetupDepthAndCulling(void)
12071 // submodels are biased to avoid z-fighting with world surfaces that they
12072 // may be exactly overlapping (avoids z-fighting artifacts on certain
12073 // doors and things in Quake maps)
12074 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
12075 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
12076 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
12077 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12080 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12082 // transparent sky would be ridiculous
12083 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12085 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12086 skyrenderlater = true;
12087 RSurf_SetupDepthAndCulling();
12088 GL_DepthMask(true);
12089 // LordHavoc: HalfLife maps have freaky skypolys so don't use
12090 // skymasking on them, and Quake3 never did sky masking (unlike
12091 // software Quake and software Quake2), so disable the sky masking
12092 // in Quake3 maps as it causes problems with q3map2 sky tricks,
12093 // and skymasking also looks very bad when noclipping outside the
12094 // level, so don't use it then either.
12095 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
12097 R_Mesh_ResetTextureState();
12098 if (skyrendermasked)
12100 R_SetupShader_DepthOrShadow();
12101 // depth-only (masking)
12102 GL_ColorMask(0,0,0,0);
12103 // just to make sure that braindead drivers don't draw
12104 // anything despite that colormask...
12105 GL_BlendFunc(GL_ZERO, GL_ONE);
12106 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12107 if (rsurface.batchvertex3fbuffer)
12108 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
12110 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
12114 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12116 GL_BlendFunc(GL_ONE, GL_ZERO);
12117 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12118 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
12119 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12122 if (skyrendermasked)
12123 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12125 R_Mesh_ResetTextureState();
12126 GL_Color(1, 1, 1, 1);
12129 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
12130 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
12131 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12133 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
12137 // render screenspace normalmap to texture
12138 GL_DepthMask(true);
12139 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
12144 // bind lightmap texture
12146 // water/refraction/reflection/camera surfaces have to be handled specially
12147 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
12149 int start, end, startplaneindex;
12150 for (start = 0;start < texturenumsurfaces;start = end)
12152 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
12153 if(startplaneindex < 0)
12155 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
12156 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
12160 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
12162 // now that we have a batch using the same planeindex, render it
12163 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
12165 // render water or distortion background
12166 GL_DepthMask(true);
12167 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));
12169 // blend surface on top
12170 GL_DepthMask(false);
12171 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
12174 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
12176 // render surface with reflection texture as input
12177 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12178 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));
12185 // render surface batch normally
12186 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12187 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
12191 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12193 // OpenGL 1.3 path - anything not completely ancient
12194 qboolean applycolor;
12197 const texturelayer_t *layer;
12198 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);
12199 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12201 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12204 int layertexrgbscale;
12205 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12207 if (layerindex == 0)
12208 GL_AlphaTest(true);
12211 GL_AlphaTest(false);
12212 GL_DepthFunc(GL_EQUAL);
12215 GL_DepthMask(layer->depthmask && writedepth);
12216 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12217 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
12219 layertexrgbscale = 4;
12220 VectorScale(layer->color, 0.25f, layercolor);
12222 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
12224 layertexrgbscale = 2;
12225 VectorScale(layer->color, 0.5f, layercolor);
12229 layertexrgbscale = 1;
12230 VectorScale(layer->color, 1.0f, layercolor);
12232 layercolor[3] = layer->color[3];
12233 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
12234 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12235 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12236 switch (layer->type)
12238 case TEXTURELAYERTYPE_LITTEXTURE:
12239 // single-pass lightmapped texture with 2x rgbscale
12240 R_Mesh_TexBind(0, r_texture_white);
12241 R_Mesh_TexMatrix(0, NULL);
12242 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12243 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12244 R_Mesh_TexBind(1, layer->texture);
12245 R_Mesh_TexMatrix(1, &layer->texmatrix);
12246 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12247 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12248 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12249 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12250 else if (FAKELIGHT_ENABLED)
12251 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12252 else if (rsurface.uselightmaptexture)
12253 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12255 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12257 case TEXTURELAYERTYPE_TEXTURE:
12258 // singletexture unlit texture with transparency support
12259 R_Mesh_TexBind(0, layer->texture);
12260 R_Mesh_TexMatrix(0, &layer->texmatrix);
12261 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12262 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12263 R_Mesh_TexBind(1, 0);
12264 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12265 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12267 case TEXTURELAYERTYPE_FOG:
12268 // singletexture fogging
12269 if (layer->texture)
12271 R_Mesh_TexBind(0, layer->texture);
12272 R_Mesh_TexMatrix(0, &layer->texmatrix);
12273 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12274 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12278 R_Mesh_TexBind(0, 0);
12279 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12281 R_Mesh_TexBind(1, 0);
12282 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12283 // generate a color array for the fog pass
12284 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
12285 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
12289 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12292 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12294 GL_DepthFunc(GL_LEQUAL);
12295 GL_AlphaTest(false);
12299 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12301 // OpenGL 1.1 - crusty old voodoo path
12304 const texturelayer_t *layer;
12305 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);
12306 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12308 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12310 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12312 if (layerindex == 0)
12313 GL_AlphaTest(true);
12316 GL_AlphaTest(false);
12317 GL_DepthFunc(GL_EQUAL);
12320 GL_DepthMask(layer->depthmask && writedepth);
12321 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12322 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12323 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12324 switch (layer->type)
12326 case TEXTURELAYERTYPE_LITTEXTURE:
12327 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
12329 // two-pass lit texture with 2x rgbscale
12330 // first the lightmap pass
12331 R_Mesh_TexBind(0, r_texture_white);
12332 R_Mesh_TexMatrix(0, NULL);
12333 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12334 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12335 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12336 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
12337 else if (FAKELIGHT_ENABLED)
12338 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
12339 else if (rsurface.uselightmaptexture)
12340 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
12342 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
12343 // then apply the texture to it
12344 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
12345 R_Mesh_TexBind(0, layer->texture);
12346 R_Mesh_TexMatrix(0, &layer->texmatrix);
12347 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12348 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12349 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);
12353 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
12354 R_Mesh_TexBind(0, layer->texture);
12355 R_Mesh_TexMatrix(0, &layer->texmatrix);
12356 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12357 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12358 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12359 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);
12361 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);
12364 case TEXTURELAYERTYPE_TEXTURE:
12365 // singletexture unlit texture with transparency support
12366 R_Mesh_TexBind(0, layer->texture);
12367 R_Mesh_TexMatrix(0, &layer->texmatrix);
12368 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12369 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12370 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);
12372 case TEXTURELAYERTYPE_FOG:
12373 // singletexture fogging
12374 if (layer->texture)
12376 R_Mesh_TexBind(0, layer->texture);
12377 R_Mesh_TexMatrix(0, &layer->texmatrix);
12378 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12379 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12383 R_Mesh_TexBind(0, 0);
12384 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12386 // generate a color array for the fog pass
12387 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
12388 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
12392 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12395 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12397 GL_DepthFunc(GL_LEQUAL);
12398 GL_AlphaTest(false);
12402 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12406 r_vertexgeneric_t *batchvertex;
12409 // R_Mesh_ResetTextureState();
12410 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12412 if(rsurface.texture && rsurface.texture->currentskinframe)
12414 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
12415 c[3] *= rsurface.texture->currentalpha;
12425 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
12427 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
12428 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
12429 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
12432 // brighten it up (as texture value 127 means "unlit")
12433 c[0] *= 2 * r_refdef.view.colorscale;
12434 c[1] *= 2 * r_refdef.view.colorscale;
12435 c[2] *= 2 * r_refdef.view.colorscale;
12437 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
12438 c[3] *= r_wateralpha.value;
12440 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
12442 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12443 GL_DepthMask(false);
12445 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
12447 GL_BlendFunc(GL_ONE, GL_ONE);
12448 GL_DepthMask(false);
12450 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12452 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
12453 GL_DepthMask(false);
12455 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
12457 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
12458 GL_DepthMask(false);
12462 GL_BlendFunc(GL_ONE, GL_ZERO);
12463 GL_DepthMask(writedepth);
12466 if (r_showsurfaces.integer == 3)
12468 rsurface.passcolor4f = NULL;
12470 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
12472 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12474 rsurface.passcolor4f = NULL;
12475 rsurface.passcolor4f_vertexbuffer = 0;
12476 rsurface.passcolor4f_bufferoffset = 0;
12478 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12480 qboolean applycolor = true;
12483 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12485 r_refdef.lightmapintensity = 1;
12486 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
12487 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12489 else if (FAKELIGHT_ENABLED)
12491 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12493 r_refdef.lightmapintensity = r_fakelight_intensity.value;
12494 RSurf_DrawBatch_GL11_ApplyFakeLight();
12495 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12499 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12501 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12502 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12503 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12506 if(!rsurface.passcolor4f)
12507 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
12509 RSurf_DrawBatch_GL11_ApplyAmbient();
12510 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
12511 if(r_refdef.fogenabled)
12512 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
12513 RSurf_DrawBatch_GL11_ClampColor();
12515 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
12516 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12519 else if (!r_refdef.view.showdebug)
12521 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12522 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12523 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12525 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12526 Vector4Set(batchvertex[vi].color4ub, 0, 0, 0, 255);
12528 R_Mesh_PrepareVertices_Generic_Unlock();
12531 else if (r_showsurfaces.integer == 4)
12533 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12534 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12535 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12537 unsigned char c = vi << 3;
12538 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12539 Vector4Set(batchvertex[vi].color4ub, c, c, c, 255);
12541 R_Mesh_PrepareVertices_Generic_Unlock();
12544 else if (r_showsurfaces.integer == 2)
12547 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12548 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
12549 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
12551 unsigned char c = (j + rsurface.batchfirsttriangle) << 3;
12552 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
12553 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
12554 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
12555 Vector4Set(batchvertex[j*3+0].color4ub, c, c, c, 255);
12556 Vector4Set(batchvertex[j*3+1].color4ub, c, c, c, 255);
12557 Vector4Set(batchvertex[j*3+2].color4ub, c, c, c, 255);
12559 R_Mesh_PrepareVertices_Generic_Unlock();
12560 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
12564 int texturesurfaceindex;
12566 const msurface_t *surface;
12567 unsigned char surfacecolor4ub[4];
12568 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12569 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
12571 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
12573 surface = texturesurfacelist[texturesurfaceindex];
12574 k = (int)(((size_t)surface) / sizeof(msurface_t));
12575 Vector4Set(surfacecolor4ub, (k & 0xF) << 4, (k & 0xF0), (k & 0xF00) >> 4, 255);
12576 for (j = 0;j < surface->num_vertices;j++)
12578 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12579 Vector4Copy(surfacecolor4ub, batchvertex[vi].color4ub);
12583 R_Mesh_PrepareVertices_Generic_Unlock();
12588 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12591 RSurf_SetupDepthAndCulling();
12592 if (r_showsurfaces.integer)
12594 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12597 switch (vid.renderpath)
12599 case RENDERPATH_GL20:
12600 case RENDERPATH_D3D9:
12601 case RENDERPATH_D3D10:
12602 case RENDERPATH_D3D11:
12603 case RENDERPATH_SOFT:
12604 case RENDERPATH_GLES2:
12605 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12607 case RENDERPATH_GL13:
12608 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
12610 case RENDERPATH_GL11:
12611 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
12617 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12620 RSurf_SetupDepthAndCulling();
12621 if (r_showsurfaces.integer)
12623 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12626 switch (vid.renderpath)
12628 case RENDERPATH_GL20:
12629 case RENDERPATH_D3D9:
12630 case RENDERPATH_D3D10:
12631 case RENDERPATH_D3D11:
12632 case RENDERPATH_SOFT:
12633 case RENDERPATH_GLES2:
12634 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12636 case RENDERPATH_GL13:
12637 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
12639 case RENDERPATH_GL11:
12640 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
12646 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
12649 int texturenumsurfaces, endsurface;
12650 texture_t *texture;
12651 const msurface_t *surface;
12652 #define MAXBATCH_TRANSPARENTSURFACES 256
12653 const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
12655 // if the model is static it doesn't matter what value we give for
12656 // wantnormals and wanttangents, so this logic uses only rules applicable
12657 // to a model, knowing that they are meaningless otherwise
12658 if (ent == r_refdef.scene.worldentity)
12659 RSurf_ActiveWorldEntity();
12660 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12661 RSurf_ActiveModelEntity(ent, false, false, false);
12664 switch (vid.renderpath)
12666 case RENDERPATH_GL20:
12667 case RENDERPATH_D3D9:
12668 case RENDERPATH_D3D10:
12669 case RENDERPATH_D3D11:
12670 case RENDERPATH_SOFT:
12671 case RENDERPATH_GLES2:
12672 RSurf_ActiveModelEntity(ent, true, true, false);
12674 case RENDERPATH_GL13:
12675 case RENDERPATH_GL11:
12676 RSurf_ActiveModelEntity(ent, true, false, false);
12681 if (r_transparentdepthmasking.integer)
12683 qboolean setup = false;
12684 for (i = 0;i < numsurfaces;i = j)
12687 surface = rsurface.modelsurfaces + surfacelist[i];
12688 texture = surface->texture;
12689 rsurface.texture = R_GetCurrentTexture(texture);
12690 rsurface.lightmaptexture = NULL;
12691 rsurface.deluxemaptexture = NULL;
12692 rsurface.uselightmaptexture = false;
12693 // scan ahead until we find a different texture
12694 endsurface = min(i + 1024, numsurfaces);
12695 texturenumsurfaces = 0;
12696 texturesurfacelist[texturenumsurfaces++] = surface;
12697 for (;j < endsurface;j++)
12699 surface = rsurface.modelsurfaces + surfacelist[j];
12700 if (texture != surface->texture)
12702 texturesurfacelist[texturenumsurfaces++] = surface;
12704 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
12706 // render the range of surfaces as depth
12710 GL_ColorMask(0,0,0,0);
12712 GL_DepthTest(true);
12713 GL_BlendFunc(GL_ONE, GL_ZERO);
12714 GL_DepthMask(true);
12715 // R_Mesh_ResetTextureState();
12716 R_SetupShader_DepthOrShadow();
12718 RSurf_SetupDepthAndCulling();
12719 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
12720 if (rsurface.batchvertex3fbuffer)
12721 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
12723 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
12727 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12730 for (i = 0;i < numsurfaces;i = j)
12733 surface = rsurface.modelsurfaces + surfacelist[i];
12734 texture = surface->texture;
12735 rsurface.texture = R_GetCurrentTexture(texture);
12736 // scan ahead until we find a different texture
12737 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
12738 texturenumsurfaces = 0;
12739 texturesurfacelist[texturenumsurfaces++] = surface;
12740 if(FAKELIGHT_ENABLED)
12742 rsurface.lightmaptexture = NULL;
12743 rsurface.deluxemaptexture = NULL;
12744 rsurface.uselightmaptexture = false;
12745 for (;j < endsurface;j++)
12747 surface = rsurface.modelsurfaces + surfacelist[j];
12748 if (texture != surface->texture)
12750 texturesurfacelist[texturenumsurfaces++] = surface;
12755 rsurface.lightmaptexture = surface->lightmaptexture;
12756 rsurface.deluxemaptexture = surface->deluxemaptexture;
12757 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
12758 for (;j < endsurface;j++)
12760 surface = rsurface.modelsurfaces + surfacelist[j];
12761 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
12763 texturesurfacelist[texturenumsurfaces++] = surface;
12766 // render the range of surfaces
12767 if (ent == r_refdef.scene.worldentity)
12768 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
12770 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
12772 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12775 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
12777 // transparent surfaces get pushed off into the transparent queue
12778 int surfacelistindex;
12779 const msurface_t *surface;
12780 vec3_t tempcenter, center;
12781 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
12783 surface = texturesurfacelist[surfacelistindex];
12784 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
12785 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
12786 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
12787 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
12788 if (queueentity->transparent_offset) // transparent offset
12790 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
12791 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
12792 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
12794 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
12798 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12800 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
12802 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
12804 RSurf_SetupDepthAndCulling();
12805 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
12806 if (rsurface.batchvertex3fbuffer)
12807 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
12809 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
12813 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
12815 const entity_render_t *queueentity = r_refdef.scene.worldentity;
12818 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
12821 if (!rsurface.texture->currentnumlayers)
12823 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12824 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12826 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12828 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
12829 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
12830 else if (!rsurface.texture->currentnumlayers)
12832 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
12834 // in the deferred case, transparent surfaces were queued during prepass
12835 if (!r_shadow_usingdeferredprepass)
12836 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12840 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
12841 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
12846 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
12849 texture_t *texture;
12850 R_FrameData_SetMark();
12851 // break the surface list down into batches by texture and use of lightmapping
12852 for (i = 0;i < numsurfaces;i = j)
12855 // texture is the base texture pointer, rsurface.texture is the
12856 // current frame/skin the texture is directing us to use (for example
12857 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
12858 // use skin 1 instead)
12859 texture = surfacelist[i]->texture;
12860 rsurface.texture = R_GetCurrentTexture(texture);
12861 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
12863 // if this texture is not the kind we want, skip ahead to the next one
12864 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12868 if(FAKELIGHT_ENABLED || depthonly || prepass)
12870 rsurface.lightmaptexture = NULL;
12871 rsurface.deluxemaptexture = NULL;
12872 rsurface.uselightmaptexture = false;
12873 // simply scan ahead until we find a different texture or lightmap state
12874 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12879 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
12880 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
12881 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
12882 // simply scan ahead until we find a different texture or lightmap state
12883 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
12886 // render the range of surfaces
12887 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
12889 R_FrameData_ReturnToMark();
12892 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
12896 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
12899 if (!rsurface.texture->currentnumlayers)
12901 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12902 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12904 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12906 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
12907 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
12908 else if (!rsurface.texture->currentnumlayers)
12910 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
12912 // in the deferred case, transparent surfaces were queued during prepass
12913 if (!r_shadow_usingdeferredprepass)
12914 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12918 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
12919 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
12924 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
12927 texture_t *texture;
12928 R_FrameData_SetMark();
12929 // break the surface list down into batches by texture and use of lightmapping
12930 for (i = 0;i < numsurfaces;i = j)
12933 // texture is the base texture pointer, rsurface.texture is the
12934 // current frame/skin the texture is directing us to use (for example
12935 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
12936 // use skin 1 instead)
12937 texture = surfacelist[i]->texture;
12938 rsurface.texture = R_GetCurrentTexture(texture);
12939 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
12941 // if this texture is not the kind we want, skip ahead to the next one
12942 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12946 if(FAKELIGHT_ENABLED || depthonly || prepass)
12948 rsurface.lightmaptexture = NULL;
12949 rsurface.deluxemaptexture = NULL;
12950 rsurface.uselightmaptexture = false;
12951 // simply scan ahead until we find a different texture or lightmap state
12952 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12957 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
12958 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
12959 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
12960 // simply scan ahead until we find a different texture or lightmap state
12961 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
12964 // render the range of surfaces
12965 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
12967 R_FrameData_ReturnToMark();
12970 float locboxvertex3f[6*4*3] =
12972 1,0,1, 1,0,0, 1,1,0, 1,1,1,
12973 0,1,1, 0,1,0, 0,0,0, 0,0,1,
12974 1,1,1, 1,1,0, 0,1,0, 0,1,1,
12975 0,0,1, 0,0,0, 1,0,0, 1,0,1,
12976 0,0,1, 1,0,1, 1,1,1, 0,1,1,
12977 1,0,0, 0,0,0, 0,1,0, 1,1,0
12980 unsigned short locboxelements[6*2*3] =
12985 12,13,14, 12,14,15,
12986 16,17,18, 16,18,19,
12990 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
12993 cl_locnode_t *loc = (cl_locnode_t *)ent;
12995 float vertex3f[6*4*3];
12997 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12998 GL_DepthMask(false);
12999 GL_DepthRange(0, 1);
13000 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13001 GL_DepthTest(true);
13002 GL_CullFace(GL_NONE);
13003 R_EntityMatrix(&identitymatrix);
13005 // R_Mesh_ResetTextureState();
13007 i = surfacelist[0];
13008 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13009 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13010 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13011 surfacelist[0] < 0 ? 0.5f : 0.125f);
13013 if (VectorCompare(loc->mins, loc->maxs))
13015 VectorSet(size, 2, 2, 2);
13016 VectorMA(loc->mins, -0.5f, size, mins);
13020 VectorCopy(loc->mins, mins);
13021 VectorSubtract(loc->maxs, loc->mins, size);
13024 for (i = 0;i < 6*4*3;)
13025 for (j = 0;j < 3;j++, i++)
13026 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
13028 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
13029 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13030 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
13033 void R_DrawLocs(void)
13036 cl_locnode_t *loc, *nearestloc;
13038 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
13039 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
13041 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
13042 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
13046 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
13048 if (decalsystem->decals)
13049 Mem_Free(decalsystem->decals);
13050 memset(decalsystem, 0, sizeof(*decalsystem));
13053 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)
13056 tridecal_t *decals;
13059 // expand or initialize the system
13060 if (decalsystem->maxdecals <= decalsystem->numdecals)
13062 decalsystem_t old = *decalsystem;
13063 qboolean useshortelements;
13064 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
13065 useshortelements = decalsystem->maxdecals * 3 <= 65536;
13066 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)));
13067 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
13068 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
13069 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
13070 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
13071 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
13072 if (decalsystem->numdecals)
13073 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
13075 Mem_Free(old.decals);
13076 for (i = 0;i < decalsystem->maxdecals*3;i++)
13077 decalsystem->element3i[i] = i;
13078 if (useshortelements)
13079 for (i = 0;i < decalsystem->maxdecals*3;i++)
13080 decalsystem->element3s[i] = i;
13083 // grab a decal and search for another free slot for the next one
13084 decals = decalsystem->decals;
13085 decal = decalsystem->decals + (i = decalsystem->freedecal++);
13086 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
13088 decalsystem->freedecal = i;
13089 if (decalsystem->numdecals <= i)
13090 decalsystem->numdecals = i + 1;
13092 // initialize the decal
13094 decal->triangleindex = triangleindex;
13095 decal->surfaceindex = surfaceindex;
13096 decal->decalsequence = decalsequence;
13097 decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
13098 decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
13099 decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
13100 decal->color4ub[0][3] = 255;
13101 decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
13102 decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
13103 decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
13104 decal->color4ub[1][3] = 255;
13105 decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
13106 decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
13107 decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
13108 decal->color4ub[2][3] = 255;
13109 decal->vertex3f[0][0] = v0[0];
13110 decal->vertex3f[0][1] = v0[1];
13111 decal->vertex3f[0][2] = v0[2];
13112 decal->vertex3f[1][0] = v1[0];
13113 decal->vertex3f[1][1] = v1[1];
13114 decal->vertex3f[1][2] = v1[2];
13115 decal->vertex3f[2][0] = v2[0];
13116 decal->vertex3f[2][1] = v2[1];
13117 decal->vertex3f[2][2] = v2[2];
13118 decal->texcoord2f[0][0] = t0[0];
13119 decal->texcoord2f[0][1] = t0[1];
13120 decal->texcoord2f[1][0] = t1[0];
13121 decal->texcoord2f[1][1] = t1[1];
13122 decal->texcoord2f[2][0] = t2[0];
13123 decal->texcoord2f[2][1] = t2[1];
13126 extern cvar_t cl_decals_bias;
13127 extern cvar_t cl_decals_models;
13128 extern cvar_t cl_decals_newsystem_intensitymultiplier;
13129 // baseparms, parms, temps
13130 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)
13135 const float *vertex3f;
13137 float points[2][9][3];
13144 e = rsurface.modelelement3i + 3*triangleindex;
13146 vertex3f = rsurface.modelvertex3f;
13148 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13150 index = 3*e[cornerindex];
13151 VectorCopy(vertex3f + index, v[cornerindex]);
13154 //TriangleNormal(v[0], v[1], v[2], normal);
13155 //if (DotProduct(normal, localnormal) < 0.0f)
13157 // clip by each of the box planes formed from the projection matrix
13158 // if anything survives, we emit the decal
13159 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]);
13162 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]);
13165 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]);
13168 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]);
13171 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]);
13174 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]);
13177 // some part of the triangle survived, so we have to accept it...
13180 // dynamic always uses the original triangle
13182 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13184 index = 3*e[cornerindex];
13185 VectorCopy(vertex3f + index, v[cornerindex]);
13188 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
13190 // convert vertex positions to texcoords
13191 Matrix4x4_Transform(projection, v[cornerindex], temp);
13192 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
13193 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
13194 // calculate distance fade from the projection origin
13195 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
13196 f = bound(0.0f, f, 1.0f);
13197 c[cornerindex][0] = r * f;
13198 c[cornerindex][1] = g * f;
13199 c[cornerindex][2] = b * f;
13200 c[cornerindex][3] = 1.0f;
13201 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
13204 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);
13206 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
13207 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);
13209 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)
13211 matrix4x4_t projection;
13212 decalsystem_t *decalsystem;
13215 const msurface_t *surface;
13216 const msurface_t *surfaces;
13217 const int *surfacelist;
13218 const texture_t *texture;
13220 int numsurfacelist;
13221 int surfacelistindex;
13224 float localorigin[3];
13225 float localnormal[3];
13226 float localmins[3];
13227 float localmaxs[3];
13230 float planes[6][4];
13233 int bih_triangles_count;
13234 int bih_triangles[256];
13235 int bih_surfaces[256];
13237 decalsystem = &ent->decalsystem;
13238 model = ent->model;
13239 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
13241 R_DecalSystem_Reset(&ent->decalsystem);
13245 if (!model->brush.data_leafs && !cl_decals_models.integer)
13247 if (decalsystem->model)
13248 R_DecalSystem_Reset(decalsystem);
13252 if (decalsystem->model != model)
13253 R_DecalSystem_Reset(decalsystem);
13254 decalsystem->model = model;
13256 RSurf_ActiveModelEntity(ent, false, false, false);
13258 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
13259 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
13260 VectorNormalize(localnormal);
13261 localsize = worldsize*rsurface.inversematrixscale;
13262 localmins[0] = localorigin[0] - localsize;
13263 localmins[1] = localorigin[1] - localsize;
13264 localmins[2] = localorigin[2] - localsize;
13265 localmaxs[0] = localorigin[0] + localsize;
13266 localmaxs[1] = localorigin[1] + localsize;
13267 localmaxs[2] = localorigin[2] + localsize;
13269 //VectorCopy(localnormal, planes[4]);
13270 //VectorVectors(planes[4], planes[2], planes[0]);
13271 AnglesFromVectors(angles, localnormal, NULL, false);
13272 AngleVectors(angles, planes[0], planes[2], planes[4]);
13273 VectorNegate(planes[0], planes[1]);
13274 VectorNegate(planes[2], planes[3]);
13275 VectorNegate(planes[4], planes[5]);
13276 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
13277 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
13278 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
13279 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
13280 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
13281 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
13286 matrix4x4_t forwardprojection;
13287 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
13288 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
13293 float projectionvector[4][3];
13294 VectorScale(planes[0], ilocalsize, projectionvector[0]);
13295 VectorScale(planes[2], ilocalsize, projectionvector[1]);
13296 VectorScale(planes[4], ilocalsize, projectionvector[2]);
13297 projectionvector[0][0] = planes[0][0] * ilocalsize;
13298 projectionvector[0][1] = planes[1][0] * ilocalsize;
13299 projectionvector[0][2] = planes[2][0] * ilocalsize;
13300 projectionvector[1][0] = planes[0][1] * ilocalsize;
13301 projectionvector[1][1] = planes[1][1] * ilocalsize;
13302 projectionvector[1][2] = planes[2][1] * ilocalsize;
13303 projectionvector[2][0] = planes[0][2] * ilocalsize;
13304 projectionvector[2][1] = planes[1][2] * ilocalsize;
13305 projectionvector[2][2] = planes[2][2] * ilocalsize;
13306 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
13307 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
13308 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
13309 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
13313 dynamic = model->surfmesh.isanimated;
13314 numsurfacelist = model->nummodelsurfaces;
13315 surfacelist = model->sortedmodelsurfaces;
13316 surfaces = model->data_surfaces;
13319 bih_triangles_count = -1;
13322 if(model->render_bih.numleafs)
13323 bih = &model->render_bih;
13324 else if(model->collision_bih.numleafs)
13325 bih = &model->collision_bih;
13328 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
13329 if(bih_triangles_count == 0)
13331 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
13333 if(bih_triangles_count > 0)
13335 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
13337 surfaceindex = bih_surfaces[triangleindex];
13338 surface = surfaces + surfaceindex;
13339 texture = surface->texture;
13340 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13342 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13344 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
13349 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
13351 surfaceindex = surfacelist[surfacelistindex];
13352 surface = surfaces + surfaceindex;
13353 // check cull box first because it rejects more than any other check
13354 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
13356 // skip transparent surfaces
13357 texture = surface->texture;
13358 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13360 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13362 numtriangles = surface->num_triangles;
13363 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
13364 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
13369 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
13370 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)
13372 int renderentityindex;
13373 float worldmins[3];
13374 float worldmaxs[3];
13375 entity_render_t *ent;
13377 if (!cl_decals_newsystem.integer)
13380 worldmins[0] = worldorigin[0] - worldsize;
13381 worldmins[1] = worldorigin[1] - worldsize;
13382 worldmins[2] = worldorigin[2] - worldsize;
13383 worldmaxs[0] = worldorigin[0] + worldsize;
13384 worldmaxs[1] = worldorigin[1] + worldsize;
13385 worldmaxs[2] = worldorigin[2] + worldsize;
13387 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13389 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
13391 ent = r_refdef.scene.entities[renderentityindex];
13392 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
13395 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13399 typedef struct r_decalsystem_splatqueue_s
13401 vec3_t worldorigin;
13402 vec3_t worldnormal;
13408 r_decalsystem_splatqueue_t;
13410 int r_decalsystem_numqueued = 0;
13411 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
13413 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)
13415 r_decalsystem_splatqueue_t *queue;
13417 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
13420 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
13421 VectorCopy(worldorigin, queue->worldorigin);
13422 VectorCopy(worldnormal, queue->worldnormal);
13423 Vector4Set(queue->color, r, g, b, a);
13424 Vector4Set(queue->tcrange, s1, t1, s2, t2);
13425 queue->worldsize = worldsize;
13426 queue->decalsequence = cl.decalsequence++;
13429 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
13432 r_decalsystem_splatqueue_t *queue;
13434 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
13435 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);
13436 r_decalsystem_numqueued = 0;
13439 extern cvar_t cl_decals_max;
13440 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
13443 decalsystem_t *decalsystem = &ent->decalsystem;
13450 if (!decalsystem->numdecals)
13453 if (r_showsurfaces.integer)
13456 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13458 R_DecalSystem_Reset(decalsystem);
13462 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
13463 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
13465 if (decalsystem->lastupdatetime)
13466 frametime = (cl.time - decalsystem->lastupdatetime);
13469 decalsystem->lastupdatetime = cl.time;
13470 decal = decalsystem->decals;
13471 numdecals = decalsystem->numdecals;
13473 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13475 if (decal->color4ub[0][3])
13477 decal->lived += frametime;
13478 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
13480 memset(decal, 0, sizeof(*decal));
13481 if (decalsystem->freedecal > i)
13482 decalsystem->freedecal = i;
13486 decal = decalsystem->decals;
13487 while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
13490 // collapse the array by shuffling the tail decals into the gaps
13493 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
13494 decalsystem->freedecal++;
13495 if (decalsystem->freedecal == numdecals)
13497 decal[decalsystem->freedecal] = decal[--numdecals];
13500 decalsystem->numdecals = numdecals;
13502 if (numdecals <= 0)
13504 // if there are no decals left, reset decalsystem
13505 R_DecalSystem_Reset(decalsystem);
13509 extern skinframe_t *decalskinframe;
13510 static void R_DrawModelDecals_Entity(entity_render_t *ent)
13513 decalsystem_t *decalsystem = &ent->decalsystem;
13522 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
13525 numdecals = decalsystem->numdecals;
13529 if (r_showsurfaces.integer)
13532 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13534 R_DecalSystem_Reset(decalsystem);
13538 // if the model is static it doesn't matter what value we give for
13539 // wantnormals and wanttangents, so this logic uses only rules applicable
13540 // to a model, knowing that they are meaningless otherwise
13541 if (ent == r_refdef.scene.worldentity)
13542 RSurf_ActiveWorldEntity();
13544 RSurf_ActiveModelEntity(ent, false, false, false);
13546 decalsystem->lastupdatetime = cl.time;
13547 decal = decalsystem->decals;
13549 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
13551 // update vertex positions for animated models
13552 v3f = decalsystem->vertex3f;
13553 c4f = decalsystem->color4f;
13554 t2f = decalsystem->texcoord2f;
13555 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13557 if (!decal->color4ub[0][3])
13560 if (surfacevisible && !surfacevisible[decal->surfaceindex])
13563 // update color values for fading decals
13564 if (decal->lived >= cl_decals_time.value)
13566 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
13567 alpha *= (1.0f/255.0f);
13570 alpha = 1.0f/255.0f;
13572 c4f[ 0] = decal->color4ub[0][0] * alpha;
13573 c4f[ 1] = decal->color4ub[0][1] * alpha;
13574 c4f[ 2] = decal->color4ub[0][2] * alpha;
13576 c4f[ 4] = decal->color4ub[1][0] * alpha;
13577 c4f[ 5] = decal->color4ub[1][1] * alpha;
13578 c4f[ 6] = decal->color4ub[1][2] * alpha;
13580 c4f[ 8] = decal->color4ub[2][0] * alpha;
13581 c4f[ 9] = decal->color4ub[2][1] * alpha;
13582 c4f[10] = decal->color4ub[2][2] * alpha;
13585 t2f[0] = decal->texcoord2f[0][0];
13586 t2f[1] = decal->texcoord2f[0][1];
13587 t2f[2] = decal->texcoord2f[1][0];
13588 t2f[3] = decal->texcoord2f[1][1];
13589 t2f[4] = decal->texcoord2f[2][0];
13590 t2f[5] = decal->texcoord2f[2][1];
13592 // update vertex positions for animated models
13593 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
13595 e = rsurface.modelelement3i + 3*decal->triangleindex;
13596 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
13597 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
13598 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
13602 VectorCopy(decal->vertex3f[0], v3f);
13603 VectorCopy(decal->vertex3f[1], v3f + 3);
13604 VectorCopy(decal->vertex3f[2], v3f + 6);
13607 if (r_refdef.fogenabled)
13609 alpha = RSurf_FogVertex(v3f);
13610 VectorScale(c4f, alpha, c4f);
13611 alpha = RSurf_FogVertex(v3f + 3);
13612 VectorScale(c4f + 4, alpha, c4f + 4);
13613 alpha = RSurf_FogVertex(v3f + 6);
13614 VectorScale(c4f + 8, alpha, c4f + 8);
13625 r_refdef.stats.drawndecals += numtris;
13627 // now render the decals all at once
13628 // (this assumes they all use one particle font texture!)
13629 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);
13630 // R_Mesh_ResetTextureState();
13631 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
13632 GL_DepthMask(false);
13633 GL_DepthRange(0, 1);
13634 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
13635 GL_DepthTest(true);
13636 GL_CullFace(GL_NONE);
13637 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
13638 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
13639 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
13643 static void R_DrawModelDecals(void)
13647 // fade faster when there are too many decals
13648 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
13649 for (i = 0;i < r_refdef.scene.numentities;i++)
13650 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
13652 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
13653 for (i = 0;i < r_refdef.scene.numentities;i++)
13654 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
13655 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
13657 R_DecalSystem_ApplySplatEntitiesQueue();
13659 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
13660 for (i = 0;i < r_refdef.scene.numentities;i++)
13661 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
13663 r_refdef.stats.totaldecals += numdecals;
13665 if (r_showsurfaces.integer)
13668 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
13670 for (i = 0;i < r_refdef.scene.numentities;i++)
13672 if (!r_refdef.viewcache.entityvisible[i])
13674 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
13675 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
13679 extern cvar_t mod_collision_bih;
13680 void R_DrawDebugModel(void)
13682 entity_render_t *ent = rsurface.entity;
13683 int i, j, k, l, flagsmask;
13684 const msurface_t *surface;
13685 dp_model_t *model = ent->model;
13688 switch(vid.renderpath)
13690 case RENDERPATH_GL11:
13691 case RENDERPATH_GL13:
13692 case RENDERPATH_GL20:
13694 case RENDERPATH_D3D9:
13695 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13697 case RENDERPATH_D3D10:
13698 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13700 case RENDERPATH_D3D11:
13701 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13703 case RENDERPATH_SOFT:
13704 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13706 case RENDERPATH_GLES2:
13707 //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13711 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
13713 // R_Mesh_ResetTextureState();
13714 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13715 GL_DepthRange(0, 1);
13716 GL_DepthTest(!r_showdisabledepthtest.integer);
13717 GL_DepthMask(false);
13718 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13720 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
13724 qboolean cullbox = ent == r_refdef.scene.worldentity;
13725 const q3mbrush_t *brush;
13726 const bih_t *bih = &model->collision_bih;
13727 const bih_leaf_t *bihleaf;
13728 float vertex3f[3][3];
13729 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
13731 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
13733 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
13735 switch (bihleaf->type)
13738 brush = model->brush.data_brushes + bihleaf->itemindex;
13739 if (brush->colbrushf && brush->colbrushf->numtriangles)
13741 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);
13742 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
13743 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
13746 case BIH_COLLISIONTRIANGLE:
13747 triangleindex = bihleaf->itemindex;
13748 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
13749 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
13750 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
13751 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);
13752 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
13753 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
13755 case BIH_RENDERTRIANGLE:
13756 triangleindex = bihleaf->itemindex;
13757 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
13758 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
13759 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
13760 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);
13761 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
13762 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
13768 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13770 if (r_showtris.integer || (r_shownormals.value != 0))
13772 if (r_showdisabledepthtest.integer)
13774 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13775 GL_DepthMask(false);
13779 GL_BlendFunc(GL_ONE, GL_ZERO);
13780 GL_DepthMask(true);
13782 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
13784 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
13786 rsurface.texture = R_GetCurrentTexture(surface->texture);
13787 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
13789 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
13790 if (r_showtris.value > 0)
13792 if (!rsurface.texture->currentlayers->depthmask)
13793 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
13794 else if (ent == r_refdef.scene.worldentity)
13795 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
13797 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
13798 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
13799 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
13801 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
13804 if (r_shownormals.value < 0)
13806 qglBegin(GL_LINES);
13807 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
13809 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13810 GL_Color(0, 0, r_refdef.view.colorscale, 1);
13811 qglVertex3f(v[0], v[1], v[2]);
13812 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
13813 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
13814 qglVertex3f(v[0], v[1], v[2]);
13819 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
13821 qglBegin(GL_LINES);
13822 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
13824 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13825 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
13826 qglVertex3f(v[0], v[1], v[2]);
13827 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
13828 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
13829 qglVertex3f(v[0], v[1], v[2]);
13833 qglBegin(GL_LINES);
13834 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
13836 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13837 GL_Color(0, r_refdef.view.colorscale, 0, 1);
13838 qglVertex3f(v[0], v[1], v[2]);
13839 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
13840 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
13841 qglVertex3f(v[0], v[1], v[2]);
13845 qglBegin(GL_LINES);
13846 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
13848 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13849 GL_Color(0, 0, r_refdef.view.colorscale, 1);
13850 qglVertex3f(v[0], v[1], v[2]);
13851 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
13852 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
13853 qglVertex3f(v[0], v[1], v[2]);
13860 rsurface.texture = NULL;
13864 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
13865 int r_maxsurfacelist = 0;
13866 const msurface_t **r_surfacelist = NULL;
13867 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
13869 int i, j, endj, flagsmask;
13870 dp_model_t *model = r_refdef.scene.worldmodel;
13871 msurface_t *surfaces;
13872 unsigned char *update;
13873 int numsurfacelist = 0;
13877 if (r_maxsurfacelist < model->num_surfaces)
13879 r_maxsurfacelist = model->num_surfaces;
13881 Mem_Free((msurface_t**)r_surfacelist);
13882 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
13885 RSurf_ActiveWorldEntity();
13887 surfaces = model->data_surfaces;
13888 update = model->brushq1.lightmapupdateflags;
13890 // update light styles on this submodel
13891 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
13893 model_brush_lightstyleinfo_t *style;
13894 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
13896 if (style->value != r_refdef.scene.lightstylevalue[style->style])
13898 int *list = style->surfacelist;
13899 style->value = r_refdef.scene.lightstylevalue[style->style];
13900 for (j = 0;j < style->numsurfaces;j++)
13901 update[list[j]] = true;
13906 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
13910 R_DrawDebugModel();
13911 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13915 rsurface.lightmaptexture = NULL;
13916 rsurface.deluxemaptexture = NULL;
13917 rsurface.uselightmaptexture = false;
13918 rsurface.texture = NULL;
13919 rsurface.rtlight = NULL;
13920 numsurfacelist = 0;
13921 // add visible surfaces to draw list
13922 for (i = 0;i < model->nummodelsurfaces;i++)
13924 j = model->sortedmodelsurfaces[i];
13925 if (r_refdef.viewcache.world_surfacevisible[j])
13926 r_surfacelist[numsurfacelist++] = surfaces + j;
13928 // update lightmaps if needed
13929 if (model->brushq1.firstrender)
13931 model->brushq1.firstrender = false;
13932 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13934 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
13938 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13939 if (r_refdef.viewcache.world_surfacevisible[j])
13941 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
13943 // don't do anything if there were no surfaces
13944 if (!numsurfacelist)
13946 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13949 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
13951 // add to stats if desired
13952 if (r_speeds.integer && !skysurfaces && !depthonly)
13954 r_refdef.stats.world_surfaces += numsurfacelist;
13955 for (j = 0;j < numsurfacelist;j++)
13956 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
13959 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13962 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
13964 int i, j, endj, flagsmask;
13965 dp_model_t *model = ent->model;
13966 msurface_t *surfaces;
13967 unsigned char *update;
13968 int numsurfacelist = 0;
13972 if (r_maxsurfacelist < model->num_surfaces)
13974 r_maxsurfacelist = model->num_surfaces;
13976 Mem_Free((msurface_t **)r_surfacelist);
13977 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
13980 // if the model is static it doesn't matter what value we give for
13981 // wantnormals and wanttangents, so this logic uses only rules applicable
13982 // to a model, knowing that they are meaningless otherwise
13983 if (ent == r_refdef.scene.worldentity)
13984 RSurf_ActiveWorldEntity();
13985 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
13986 RSurf_ActiveModelEntity(ent, false, false, false);
13988 RSurf_ActiveModelEntity(ent, true, true, true);
13989 else if (depthonly)
13991 switch (vid.renderpath)
13993 case RENDERPATH_GL20:
13994 case RENDERPATH_D3D9:
13995 case RENDERPATH_D3D10:
13996 case RENDERPATH_D3D11:
13997 case RENDERPATH_SOFT:
13998 case RENDERPATH_GLES2:
13999 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
14001 case RENDERPATH_GL13:
14002 case RENDERPATH_GL11:
14003 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
14009 switch (vid.renderpath)
14011 case RENDERPATH_GL20:
14012 case RENDERPATH_D3D9:
14013 case RENDERPATH_D3D10:
14014 case RENDERPATH_D3D11:
14015 case RENDERPATH_SOFT:
14016 case RENDERPATH_GLES2:
14017 RSurf_ActiveModelEntity(ent, true, true, false);
14019 case RENDERPATH_GL13:
14020 case RENDERPATH_GL11:
14021 RSurf_ActiveModelEntity(ent, true, false, false);
14026 surfaces = model->data_surfaces;
14027 update = model->brushq1.lightmapupdateflags;
14029 // update light styles
14030 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14032 model_brush_lightstyleinfo_t *style;
14033 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14035 if (style->value != r_refdef.scene.lightstylevalue[style->style])
14037 int *list = style->surfacelist;
14038 style->value = r_refdef.scene.lightstylevalue[style->style];
14039 for (j = 0;j < style->numsurfaces;j++)
14040 update[list[j]] = true;
14045 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14049 R_DrawDebugModel();
14050 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14054 rsurface.lightmaptexture = NULL;
14055 rsurface.deluxemaptexture = NULL;
14056 rsurface.uselightmaptexture = false;
14057 rsurface.texture = NULL;
14058 rsurface.rtlight = NULL;
14059 numsurfacelist = 0;
14060 // add visible surfaces to draw list
14061 for (i = 0;i < model->nummodelsurfaces;i++)
14062 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
14063 // don't do anything if there were no surfaces
14064 if (!numsurfacelist)
14066 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14069 // update lightmaps if needed
14073 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14078 R_BuildLightMap(ent, surfaces + j);
14083 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14085 R_BuildLightMap(ent, surfaces + j);
14086 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14088 // add to stats if desired
14089 if (r_speeds.integer && !skysurfaces && !depthonly)
14091 r_refdef.stats.entities_surfaces += numsurfacelist;
14092 for (j = 0;j < numsurfacelist;j++)
14093 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
14096 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14099 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
14101 static texture_t texture;
14102 static msurface_t surface;
14103 const msurface_t *surfacelist = &surface;
14105 // fake enough texture and surface state to render this geometry
14107 texture.update_lastrenderframe = -1; // regenerate this texture
14108 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
14109 texture.currentskinframe = skinframe;
14110 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
14111 texture.offsetmapping = OFFSETMAPPING_OFF;
14112 texture.offsetscale = 1;
14113 texture.specularscalemod = 1;
14114 texture.specularpowermod = 1;
14116 surface.texture = &texture;
14117 surface.num_triangles = numtriangles;
14118 surface.num_firsttriangle = firsttriangle;
14119 surface.num_vertices = numvertices;
14120 surface.num_firstvertex = firstvertex;
14123 rsurface.texture = R_GetCurrentTexture(surface.texture);
14124 rsurface.lightmaptexture = NULL;
14125 rsurface.deluxemaptexture = NULL;
14126 rsurface.uselightmaptexture = false;
14127 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14130 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)
14132 static msurface_t surface;
14133 const msurface_t *surfacelist = &surface;
14135 // fake enough texture and surface state to render this geometry
14136 surface.texture = texture;
14137 surface.num_triangles = numtriangles;
14138 surface.num_firsttriangle = firsttriangle;
14139 surface.num_vertices = numvertices;
14140 surface.num_firstvertex = firstvertex;
14143 rsurface.texture = R_GetCurrentTexture(surface.texture);
14144 rsurface.lightmaptexture = NULL;
14145 rsurface.deluxemaptexture = NULL;
14146 rsurface.uselightmaptexture = false;
14147 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);