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_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
74 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
75 cvar_t r_transparent_alphatocoverage = {0, "r_transparent_alphatocoverage", "0", "enables alpha-to-coverage antialiasing technique on alphatest surfaces when using vid_samples 2 or higher"};
76 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
77 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
78 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)"};
79 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
80 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
81 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"};
82 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"};
83 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
84 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"};
85 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"};
86 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"};
87 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
88 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
89 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
90 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
91 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
92 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
93 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
94 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)"};
95 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)"};
96 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
97 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
98 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
99 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
101 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
102 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
103 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
105 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
106 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
107 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
108 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."};
109 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
110 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
111 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
112 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."};
113 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
114 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
115 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
116 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
117 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"};
118 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"};
119 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
120 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
121 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
122 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
123 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
124 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"};
125 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
126 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
128 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
129 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
130 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
131 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
132 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
133 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
134 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
135 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
137 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)"};
138 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"};
140 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
141 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
142 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
144 cvar_t r_viewfbo = {CVAR_SAVE, "r_viewfbo", "0", "enables use of an 8bit (1) or 16bit (2) or 32bit (3) per component float framebuffer render, which may be at a different resolution than the video mode"};
145 cvar_t r_viewscale = {CVAR_SAVE, "r_viewscale", "1", "scaling factor for resolution of the fbo rendering method, must be > 0, can be above 1 for a costly antialiasing behavior, typical values are 0.5 for 1/4th as many pixels rendered, or 1 for normal rendering"};
146 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
147 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
148 cvar_t r_viewscale_fpsscaling_multiply = {CVAR_SAVE, "r_viewscale_fpsscaling_multiply", "5", "adjust quality up or down by the frametime difference from 1.0/target, multiplied by this factor"};
149 cvar_t r_viewscale_fpsscaling_stepsize = {CVAR_SAVE, "r_viewscale_fpsscaling_stepsize", "0.01", "smallest adjustment to hit the target framerate (this value prevents minute oscillations)"};
150 cvar_t r_viewscale_fpsscaling_stepmax = {CVAR_SAVE, "r_viewscale_fpsscaling_stepmax", "1.00", "largest adjustment to hit the target framerate (this value prevents wild overshooting of the estimate)"};
151 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
153 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)"};
154 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
155 cvar_t r_glsl_offsetmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_steps", "2", "offset mapping steps (note: too high values may be not supported by your GPU)"};
156 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
157 cvar_t r_glsl_offsetmapping_reliefmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_steps", "10", "relief mapping steps (note: too high values may be not supported by your GPU)"};
158 cvar_t r_glsl_offsetmapping_reliefmapping_refinesteps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_refinesteps", "5", "relief mapping refine steps (these are a binary search executed as the last step as given by r_glsl_offsetmapping_reliefmapping_steps)"};
159 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
160 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
161 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)"};
162 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)"};
163 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)"};
164 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)"};
165 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)"};
166 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)"};
167 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)"};
168 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)"};
170 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)"};
171 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
172 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"};
173 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
174 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
175 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
176 cvar_t r_water_lowquality = {0, "r_water_lowquality", "0", "special option to accelerate water rendering, 1 disables shadows and particles, 2 disables all dynamic lights"};
178 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
179 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
180 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
181 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
183 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
184 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
185 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
186 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
187 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
188 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
189 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
191 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
192 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
193 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
194 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)"};
195 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
196 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
197 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
198 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
199 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
200 cvar_t r_hdr_irisadaptation_fade = {CVAR_SAVE, "r_hdr_irisadaptation_fade", "1", "fade rate at which value adjusts"};
202 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"};
204 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"};
206 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
208 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
210 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
211 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"};
213 cvar_t r_glsl_vertextextureblend_usebothalphas = {CVAR_SAVE, "r_glsl_vertextextureblend_usebothalphas", "0", "use both alpha layers on vertex blended surfaces, each alpha layer sets amount of 'blend leak' on another layer."};
215 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)"};
217 extern cvar_t v_glslgamma;
219 extern qboolean v_flipped_state;
221 static struct r_bloomstate_s
226 int bloomwidth, bloomheight;
228 textype_t texturetype;
229 int viewfbo; // used to check if r_viewfbo cvar has changed
231 int fbo_framebuffer; // non-zero if r_viewfbo is enabled and working
232 rtexture_t *texture_framebuffercolor; // non-NULL if fbo_screen is non-zero
233 rtexture_t *texture_framebufferdepth; // non-NULL if fbo_screen is non-zero
235 int screentexturewidth, screentextureheight;
236 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
238 int bloomtexturewidth, bloomtextureheight;
239 rtexture_t *texture_bloom;
241 // arrays for rendering the screen passes
242 float screentexcoord2f[8];
243 float bloomtexcoord2f[8];
244 float offsettexcoord2f[8];
246 r_viewport_t viewport;
250 r_waterstate_t r_waterstate;
252 /// shadow volume bsp struct with automatically growing nodes buffer
255 rtexture_t *r_texture_blanknormalmap;
256 rtexture_t *r_texture_white;
257 rtexture_t *r_texture_grey128;
258 rtexture_t *r_texture_black;
259 rtexture_t *r_texture_notexture;
260 rtexture_t *r_texture_whitecube;
261 rtexture_t *r_texture_normalizationcube;
262 rtexture_t *r_texture_fogattenuation;
263 rtexture_t *r_texture_fogheighttexture;
264 rtexture_t *r_texture_gammaramps;
265 unsigned int r_texture_gammaramps_serial;
266 //rtexture_t *r_texture_fogintensity;
267 rtexture_t *r_texture_reflectcube;
269 // TODO: hash lookups?
270 typedef struct cubemapinfo_s
277 int r_texture_numcubemaps;
278 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
280 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
281 unsigned int r_numqueries;
282 unsigned int r_maxqueries;
284 typedef struct r_qwskincache_s
286 char name[MAX_QPATH];
287 skinframe_t *skinframe;
291 static r_qwskincache_t *r_qwskincache;
292 static int r_qwskincache_size;
294 /// vertex coordinates for a quad that covers the screen exactly
295 extern const float r_screenvertex3f[12];
296 extern const float r_d3dscreenvertex3f[12];
297 const float r_screenvertex3f[12] =
304 const float r_d3dscreenvertex3f[12] =
312 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
315 for (i = 0;i < verts;i++)
326 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
329 for (i = 0;i < verts;i++)
339 // FIXME: move this to client?
342 if (gamemode == GAME_NEHAHRA)
344 Cvar_Set("gl_fogenable", "0");
345 Cvar_Set("gl_fogdensity", "0.2");
346 Cvar_Set("gl_fogred", "0.3");
347 Cvar_Set("gl_foggreen", "0.3");
348 Cvar_Set("gl_fogblue", "0.3");
350 r_refdef.fog_density = 0;
351 r_refdef.fog_red = 0;
352 r_refdef.fog_green = 0;
353 r_refdef.fog_blue = 0;
354 r_refdef.fog_alpha = 1;
355 r_refdef.fog_start = 0;
356 r_refdef.fog_end = 16384;
357 r_refdef.fog_height = 1<<30;
358 r_refdef.fog_fadedepth = 128;
359 memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
362 static void R_BuildBlankTextures(void)
364 unsigned char data[4];
365 data[2] = 128; // normal X
366 data[1] = 128; // normal Y
367 data[0] = 255; // normal Z
368 data[3] = 128; // height
369 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
374 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
379 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
384 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
387 static void R_BuildNoTexture(void)
390 unsigned char pix[16][16][4];
391 // this makes a light grey/dark grey checkerboard texture
392 for (y = 0;y < 16;y++)
394 for (x = 0;x < 16;x++)
396 if ((y < 8) ^ (x < 8))
412 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
415 static void R_BuildWhiteCube(void)
417 unsigned char data[6*1*1*4];
418 memset(data, 255, sizeof(data));
419 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
422 static void R_BuildNormalizationCube(void)
426 vec_t s, t, intensity;
429 data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
430 for (side = 0;side < 6;side++)
432 for (y = 0;y < NORMSIZE;y++)
434 for (x = 0;x < NORMSIZE;x++)
436 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
437 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
472 intensity = 127.0f / sqrt(DotProduct(v, v));
473 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
474 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
475 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
476 data[((side*64+y)*64+x)*4+3] = 255;
480 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
484 static void R_BuildFogTexture(void)
488 unsigned char data1[FOGWIDTH][4];
489 //unsigned char data2[FOGWIDTH][4];
492 r_refdef.fogmasktable_start = r_refdef.fog_start;
493 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
494 r_refdef.fogmasktable_range = r_refdef.fogrange;
495 r_refdef.fogmasktable_density = r_refdef.fog_density;
497 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
498 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
500 d = (x * r - r_refdef.fogmasktable_start);
501 if(developer_extra.integer)
502 Con_DPrintf("%f ", d);
504 if (r_fog_exp2.integer)
505 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
507 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
508 if(developer_extra.integer)
509 Con_DPrintf(" : %f ", alpha);
510 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
511 if(developer_extra.integer)
512 Con_DPrintf(" = %f\n", alpha);
513 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
516 for (x = 0;x < FOGWIDTH;x++)
518 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
523 //data2[x][0] = 255 - b;
524 //data2[x][1] = 255 - b;
525 //data2[x][2] = 255 - b;
528 if (r_texture_fogattenuation)
530 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
531 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
535 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
536 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
540 static void R_BuildFogHeightTexture(void)
542 unsigned char *inpixels;
550 strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
551 if (r_refdef.fogheighttexturename[0])
552 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
555 r_refdef.fog_height_tablesize = 0;
556 if (r_texture_fogheighttexture)
557 R_FreeTexture(r_texture_fogheighttexture);
558 r_texture_fogheighttexture = NULL;
559 if (r_refdef.fog_height_table2d)
560 Mem_Free(r_refdef.fog_height_table2d);
561 r_refdef.fog_height_table2d = NULL;
562 if (r_refdef.fog_height_table1d)
563 Mem_Free(r_refdef.fog_height_table1d);
564 r_refdef.fog_height_table1d = NULL;
568 r_refdef.fog_height_tablesize = size;
569 r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
570 r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
571 memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
573 // LordHavoc: now the magic - what is that table2d for? it is a cooked
574 // average fog color table accounting for every fog layer between a point
575 // and the camera. (Note: attenuation is handled separately!)
576 for (y = 0;y < size;y++)
578 for (x = 0;x < size;x++)
584 for (j = x;j <= y;j++)
586 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
592 for (j = x;j >= y;j--)
594 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
599 r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
600 r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
601 r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
602 r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
605 r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
608 //=======================================================================================================================================================
610 static const char *builtinshaderstring =
611 #include "shader_glsl.h"
614 const char *builtinhlslshaderstring =
615 #include "shader_hlsl.h"
618 char *glslshaderstring = NULL;
619 char *hlslshaderstring = NULL;
621 //=======================================================================================================================================================
623 typedef struct shaderpermutationinfo_s
628 shaderpermutationinfo_t;
630 typedef struct shadermodeinfo_s
632 const char *vertexfilename;
633 const char *geometryfilename;
634 const char *fragmentfilename;
640 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
641 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
643 {"#define USEDIFFUSE\n", " diffuse"},
644 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
645 {"#define USEVIEWTINT\n", " viewtint"},
646 {"#define USECOLORMAPPING\n", " colormapping"},
647 {"#define USESATURATION\n", " saturation"},
648 {"#define USEFOGINSIDE\n", " foginside"},
649 {"#define USEFOGOUTSIDE\n", " fogoutside"},
650 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
651 {"#define USEFOGALPHAHACK\n", " fogalphahack"},
652 {"#define USEGAMMARAMPS\n", " gammaramps"},
653 {"#define USECUBEFILTER\n", " cubefilter"},
654 {"#define USEGLOW\n", " glow"},
655 {"#define USEBLOOM\n", " bloom"},
656 {"#define USESPECULAR\n", " specular"},
657 {"#define USEPOSTPROCESSING\n", " postprocessing"},
658 {"#define USEREFLECTION\n", " reflection"},
659 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
660 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
661 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
662 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
663 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
664 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
665 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
666 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
667 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
668 {"#define USEALPHAKILL\n", " alphakill"},
669 {"#define USEREFLECTCUBE\n", " reflectcube"},
670 {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
671 {"#define USEBOUNCEGRID\n", " bouncegrid"},
672 {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
673 {"#define USETRIPPY\n", " trippy"},
676 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
677 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
679 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
680 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
681 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
682 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
683 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
684 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
685 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
686 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
687 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
688 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
689 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
690 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
691 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
692 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
693 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
694 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
697 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
699 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
700 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
701 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
702 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
703 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
704 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
705 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
706 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
707 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
708 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
709 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
710 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
711 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
712 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
713 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
714 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
717 struct r_glsl_permutation_s;
718 typedef struct r_glsl_permutation_s
721 struct r_glsl_permutation_s *hashnext;
723 unsigned int permutation;
725 /// indicates if we have tried compiling this permutation already
727 /// 0 if compilation failed
729 // texture units assigned to each detected uniform
730 int tex_Texture_First;
731 int tex_Texture_Second;
732 int tex_Texture_GammaRamps;
733 int tex_Texture_Normal;
734 int tex_Texture_Color;
735 int tex_Texture_Gloss;
736 int tex_Texture_Glow;
737 int tex_Texture_SecondaryNormal;
738 int tex_Texture_SecondaryColor;
739 int tex_Texture_SecondaryGloss;
740 int tex_Texture_SecondaryGlow;
741 int tex_Texture_Pants;
742 int tex_Texture_Shirt;
743 int tex_Texture_FogHeightTexture;
744 int tex_Texture_FogMask;
745 int tex_Texture_Lightmap;
746 int tex_Texture_Deluxemap;
747 int tex_Texture_Attenuation;
748 int tex_Texture_Cube;
749 int tex_Texture_Refraction;
750 int tex_Texture_Reflection;
751 int tex_Texture_ShadowMap2D;
752 int tex_Texture_CubeProjection;
753 int tex_Texture_ScreenDepth;
754 int tex_Texture_ScreenNormalMap;
755 int tex_Texture_ScreenDiffuse;
756 int tex_Texture_ScreenSpecular;
757 int tex_Texture_ReflectMask;
758 int tex_Texture_ReflectCube;
759 int tex_Texture_BounceGrid;
760 /// locations of detected uniforms in program object, or -1 if not found
761 int loc_Texture_First;
762 int loc_Texture_Second;
763 int loc_Texture_GammaRamps;
764 int loc_Texture_Normal;
765 int loc_Texture_Color;
766 int loc_Texture_Gloss;
767 int loc_Texture_Glow;
768 int loc_Texture_SecondaryNormal;
769 int loc_Texture_SecondaryColor;
770 int loc_Texture_SecondaryGloss;
771 int loc_Texture_SecondaryGlow;
772 int loc_Texture_Pants;
773 int loc_Texture_Shirt;
774 int loc_Texture_FogHeightTexture;
775 int loc_Texture_FogMask;
776 int loc_Texture_Lightmap;
777 int loc_Texture_Deluxemap;
778 int loc_Texture_Attenuation;
779 int loc_Texture_Cube;
780 int loc_Texture_Refraction;
781 int loc_Texture_Reflection;
782 int loc_Texture_ShadowMap2D;
783 int loc_Texture_CubeProjection;
784 int loc_Texture_ScreenDepth;
785 int loc_Texture_ScreenNormalMap;
786 int loc_Texture_ScreenDiffuse;
787 int loc_Texture_ScreenSpecular;
788 int loc_Texture_ReflectMask;
789 int loc_Texture_ReflectCube;
790 int loc_Texture_BounceGrid;
792 int loc_BloomBlur_Parameters;
794 int loc_Color_Ambient;
795 int loc_Color_Diffuse;
796 int loc_Color_Specular;
800 int loc_DeferredColor_Ambient;
801 int loc_DeferredColor_Diffuse;
802 int loc_DeferredColor_Specular;
803 int loc_DeferredMod_Diffuse;
804 int loc_DeferredMod_Specular;
805 int loc_DistortScaleRefractReflect;
808 int loc_FogHeightFade;
810 int loc_FogPlaneViewDist;
811 int loc_FogRangeRecip;
814 int loc_LightPosition;
815 int loc_OffsetMapping_ScaleSteps;
817 int loc_ReflectColor;
818 int loc_ReflectFactor;
819 int loc_ReflectOffset;
820 int loc_RefractColor;
822 int loc_ScreenCenterRefractReflect;
823 int loc_ScreenScaleRefractReflect;
824 int loc_ScreenToDepth;
825 int loc_ShadowMap_Parameters;
826 int loc_ShadowMap_TextureScale;
827 int loc_SpecularPower;
832 int loc_ViewTintColor;
834 int loc_ModelToLight;
836 int loc_BackgroundTexMatrix;
837 int loc_ModelViewProjectionMatrix;
838 int loc_ModelViewMatrix;
839 int loc_PixelToScreenTexCoord;
840 int loc_ModelToReflectCube;
841 int loc_ShadowMapMatrix;
842 int loc_BloomColorSubtract;
843 int loc_NormalmapScrollBlend;
844 int loc_BounceGridMatrix;
845 int loc_BounceGridIntensity;
847 r_glsl_permutation_t;
849 #define SHADERPERMUTATION_HASHSIZE 256
852 // non-degradable "lightweight" shader parameters to keep the permutations simpler
853 // these can NOT degrade! only use for simple stuff
856 SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
857 SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
858 SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
859 SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
860 SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
861 SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5, ///< postprocess uservec4 is enabled
862 SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6 // use both alpha layers while blending materials, allows more advanced microblending
864 #define SHADERSTATICPARMS_COUNT 7
866 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
867 static int shaderstaticparms_count = 0;
869 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
870 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
871 qboolean R_CompileShader_CheckStaticParms(void)
873 static int r_compileshader_staticparms_save[1];
874 memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
875 memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
878 if (r_glsl_saturation_redcompensate.integer)
879 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
880 if (r_glsl_vertextextureblend_usebothalphas.integer)
881 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
882 if (r_shadow_glossexact.integer)
883 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
884 if (r_glsl_postprocess.integer)
886 if (r_glsl_postprocess_uservec1_enable.integer)
887 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
888 if (r_glsl_postprocess_uservec2_enable.integer)
889 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
890 if (r_glsl_postprocess_uservec3_enable.integer)
891 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
892 if (r_glsl_postprocess_uservec4_enable.integer)
893 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
895 return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
898 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
899 if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
900 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
902 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
903 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
905 shaderstaticparms_count = 0;
908 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
909 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
910 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
911 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
912 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
913 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
914 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
917 /// information about each possible shader permutation
918 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
919 /// currently selected permutation
920 r_glsl_permutation_t *r_glsl_permutation;
921 /// storage for permutations linked in the hash table
922 memexpandablearray_t r_glsl_permutationarray;
924 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
926 //unsigned int hashdepth = 0;
927 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
928 r_glsl_permutation_t *p;
929 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
931 if (p->mode == mode && p->permutation == permutation)
933 //if (hashdepth > 10)
934 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
939 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
941 p->permutation = permutation;
942 p->hashnext = r_glsl_permutationhash[mode][hashindex];
943 r_glsl_permutationhash[mode][hashindex] = p;
944 //if (hashdepth > 10)
945 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
949 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
952 if (!filename || !filename[0])
954 if (!strcmp(filename, "glsl/default.glsl"))
956 if (!glslshaderstring)
958 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
959 if (glslshaderstring)
960 Con_DPrintf("Loading shaders from file %s...\n", filename);
962 glslshaderstring = (char *)builtinshaderstring;
964 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
965 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
968 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
971 if (printfromdisknotice)
972 Con_DPrintf("from disk %s... ", filename);
978 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
982 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
983 char *vertexstring, *geometrystring, *fragmentstring;
984 char permutationname[256];
985 int vertstrings_count = 0;
986 int geomstrings_count = 0;
987 int fragstrings_count = 0;
988 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
989 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
990 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
997 permutationname[0] = 0;
998 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
999 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1000 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1002 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1004 // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1005 if(vid.support.gl20shaders130)
1007 vertstrings_list[vertstrings_count++] = "#version 130\n";
1008 geomstrings_list[geomstrings_count++] = "#version 130\n";
1009 fragstrings_list[fragstrings_count++] = "#version 130\n";
1010 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1011 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1012 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1015 // the first pretext is which type of shader to compile as
1016 // (later these will all be bound together as a program object)
1017 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1018 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1019 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1021 // the second pretext is the mode (for example a light source)
1022 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1023 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1024 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1025 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1027 // now add all the permutation pretexts
1028 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1030 if (permutation & (1<<i))
1032 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1033 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1034 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1035 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1039 // keep line numbers correct
1040 vertstrings_list[vertstrings_count++] = "\n";
1041 geomstrings_list[geomstrings_count++] = "\n";
1042 fragstrings_list[fragstrings_count++] = "\n";
1047 R_CompileShader_AddStaticParms(mode, permutation);
1048 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1049 vertstrings_count += shaderstaticparms_count;
1050 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1051 geomstrings_count += shaderstaticparms_count;
1052 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1053 fragstrings_count += shaderstaticparms_count;
1055 // now append the shader text itself
1056 vertstrings_list[vertstrings_count++] = vertexstring;
1057 geomstrings_list[geomstrings_count++] = geometrystring;
1058 fragstrings_list[fragstrings_count++] = fragmentstring;
1060 // if any sources were NULL, clear the respective list
1062 vertstrings_count = 0;
1063 if (!geometrystring)
1064 geomstrings_count = 0;
1065 if (!fragmentstring)
1066 fragstrings_count = 0;
1068 // compile the shader program
1069 if (vertstrings_count + geomstrings_count + fragstrings_count)
1070 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1074 qglUseProgram(p->program);CHECKGLERROR
1075 // look up all the uniform variable names we care about, so we don't
1076 // have to look them up every time we set them
1078 p->loc_Texture_First = qglGetUniformLocation(p->program, "Texture_First");
1079 p->loc_Texture_Second = qglGetUniformLocation(p->program, "Texture_Second");
1080 p->loc_Texture_GammaRamps = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1081 p->loc_Texture_Normal = qglGetUniformLocation(p->program, "Texture_Normal");
1082 p->loc_Texture_Color = qglGetUniformLocation(p->program, "Texture_Color");
1083 p->loc_Texture_Gloss = qglGetUniformLocation(p->program, "Texture_Gloss");
1084 p->loc_Texture_Glow = qglGetUniformLocation(p->program, "Texture_Glow");
1085 p->loc_Texture_SecondaryNormal = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1086 p->loc_Texture_SecondaryColor = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1087 p->loc_Texture_SecondaryGloss = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1088 p->loc_Texture_SecondaryGlow = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1089 p->loc_Texture_Pants = qglGetUniformLocation(p->program, "Texture_Pants");
1090 p->loc_Texture_Shirt = qglGetUniformLocation(p->program, "Texture_Shirt");
1091 p->loc_Texture_FogHeightTexture = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1092 p->loc_Texture_FogMask = qglGetUniformLocation(p->program, "Texture_FogMask");
1093 p->loc_Texture_Lightmap = qglGetUniformLocation(p->program, "Texture_Lightmap");
1094 p->loc_Texture_Deluxemap = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1095 p->loc_Texture_Attenuation = qglGetUniformLocation(p->program, "Texture_Attenuation");
1096 p->loc_Texture_Cube = qglGetUniformLocation(p->program, "Texture_Cube");
1097 p->loc_Texture_Refraction = qglGetUniformLocation(p->program, "Texture_Refraction");
1098 p->loc_Texture_Reflection = qglGetUniformLocation(p->program, "Texture_Reflection");
1099 p->loc_Texture_ShadowMap2D = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1100 p->loc_Texture_CubeProjection = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1101 p->loc_Texture_ScreenDepth = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1102 p->loc_Texture_ScreenNormalMap = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1103 p->loc_Texture_ScreenDiffuse = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1104 p->loc_Texture_ScreenSpecular = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1105 p->loc_Texture_ReflectMask = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1106 p->loc_Texture_ReflectCube = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1107 p->loc_Texture_BounceGrid = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1108 p->loc_Alpha = qglGetUniformLocation(p->program, "Alpha");
1109 p->loc_BloomBlur_Parameters = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1110 p->loc_ClientTime = qglGetUniformLocation(p->program, "ClientTime");
1111 p->loc_Color_Ambient = qglGetUniformLocation(p->program, "Color_Ambient");
1112 p->loc_Color_Diffuse = qglGetUniformLocation(p->program, "Color_Diffuse");
1113 p->loc_Color_Specular = qglGetUniformLocation(p->program, "Color_Specular");
1114 p->loc_Color_Glow = qglGetUniformLocation(p->program, "Color_Glow");
1115 p->loc_Color_Pants = qglGetUniformLocation(p->program, "Color_Pants");
1116 p->loc_Color_Shirt = qglGetUniformLocation(p->program, "Color_Shirt");
1117 p->loc_DeferredColor_Ambient = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1118 p->loc_DeferredColor_Diffuse = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1119 p->loc_DeferredColor_Specular = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1120 p->loc_DeferredMod_Diffuse = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1121 p->loc_DeferredMod_Specular = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1122 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1123 p->loc_EyePosition = qglGetUniformLocation(p->program, "EyePosition");
1124 p->loc_FogColor = qglGetUniformLocation(p->program, "FogColor");
1125 p->loc_FogHeightFade = qglGetUniformLocation(p->program, "FogHeightFade");
1126 p->loc_FogPlane = qglGetUniformLocation(p->program, "FogPlane");
1127 p->loc_FogPlaneViewDist = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1128 p->loc_FogRangeRecip = qglGetUniformLocation(p->program, "FogRangeRecip");
1129 p->loc_LightColor = qglGetUniformLocation(p->program, "LightColor");
1130 p->loc_LightDir = qglGetUniformLocation(p->program, "LightDir");
1131 p->loc_LightPosition = qglGetUniformLocation(p->program, "LightPosition");
1132 p->loc_OffsetMapping_ScaleSteps = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1133 p->loc_PixelSize = qglGetUniformLocation(p->program, "PixelSize");
1134 p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor");
1135 p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor");
1136 p->loc_ReflectOffset = qglGetUniformLocation(p->program, "ReflectOffset");
1137 p->loc_RefractColor = qglGetUniformLocation(p->program, "RefractColor");
1138 p->loc_Saturation = qglGetUniformLocation(p->program, "Saturation");
1139 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1140 p->loc_ScreenScaleRefractReflect = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1141 p->loc_ScreenToDepth = qglGetUniformLocation(p->program, "ScreenToDepth");
1142 p->loc_ShadowMap_Parameters = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1143 p->loc_ShadowMap_TextureScale = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1144 p->loc_SpecularPower = qglGetUniformLocation(p->program, "SpecularPower");
1145 p->loc_UserVec1 = qglGetUniformLocation(p->program, "UserVec1");
1146 p->loc_UserVec2 = qglGetUniformLocation(p->program, "UserVec2");
1147 p->loc_UserVec3 = qglGetUniformLocation(p->program, "UserVec3");
1148 p->loc_UserVec4 = qglGetUniformLocation(p->program, "UserVec4");
1149 p->loc_ViewTintColor = qglGetUniformLocation(p->program, "ViewTintColor");
1150 p->loc_ViewToLight = qglGetUniformLocation(p->program, "ViewToLight");
1151 p->loc_ModelToLight = qglGetUniformLocation(p->program, "ModelToLight");
1152 p->loc_TexMatrix = qglGetUniformLocation(p->program, "TexMatrix");
1153 p->loc_BackgroundTexMatrix = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1154 p->loc_ModelViewMatrix = qglGetUniformLocation(p->program, "ModelViewMatrix");
1155 p->loc_ModelViewProjectionMatrix = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1156 p->loc_PixelToScreenTexCoord = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1157 p->loc_ModelToReflectCube = qglGetUniformLocation(p->program, "ModelToReflectCube");
1158 p->loc_ShadowMapMatrix = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1159 p->loc_BloomColorSubtract = qglGetUniformLocation(p->program, "BloomColorSubtract");
1160 p->loc_NormalmapScrollBlend = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1161 p->loc_BounceGridMatrix = qglGetUniformLocation(p->program, "BounceGridMatrix");
1162 p->loc_BounceGridIntensity = qglGetUniformLocation(p->program, "BounceGridIntensity");
1163 // initialize the samplers to refer to the texture units we use
1164 p->tex_Texture_First = -1;
1165 p->tex_Texture_Second = -1;
1166 p->tex_Texture_GammaRamps = -1;
1167 p->tex_Texture_Normal = -1;
1168 p->tex_Texture_Color = -1;
1169 p->tex_Texture_Gloss = -1;
1170 p->tex_Texture_Glow = -1;
1171 p->tex_Texture_SecondaryNormal = -1;
1172 p->tex_Texture_SecondaryColor = -1;
1173 p->tex_Texture_SecondaryGloss = -1;
1174 p->tex_Texture_SecondaryGlow = -1;
1175 p->tex_Texture_Pants = -1;
1176 p->tex_Texture_Shirt = -1;
1177 p->tex_Texture_FogHeightTexture = -1;
1178 p->tex_Texture_FogMask = -1;
1179 p->tex_Texture_Lightmap = -1;
1180 p->tex_Texture_Deluxemap = -1;
1181 p->tex_Texture_Attenuation = -1;
1182 p->tex_Texture_Cube = -1;
1183 p->tex_Texture_Refraction = -1;
1184 p->tex_Texture_Reflection = -1;
1185 p->tex_Texture_ShadowMap2D = -1;
1186 p->tex_Texture_CubeProjection = -1;
1187 p->tex_Texture_ScreenDepth = -1;
1188 p->tex_Texture_ScreenNormalMap = -1;
1189 p->tex_Texture_ScreenDiffuse = -1;
1190 p->tex_Texture_ScreenSpecular = -1;
1191 p->tex_Texture_ReflectMask = -1;
1192 p->tex_Texture_ReflectCube = -1;
1193 p->tex_Texture_BounceGrid = -1;
1195 if (p->loc_Texture_First >= 0) {p->tex_Texture_First = sampler;qglUniform1i(p->loc_Texture_First , sampler);sampler++;}
1196 if (p->loc_Texture_Second >= 0) {p->tex_Texture_Second = sampler;qglUniform1i(p->loc_Texture_Second , sampler);sampler++;}
1197 if (p->loc_Texture_GammaRamps >= 0) {p->tex_Texture_GammaRamps = sampler;qglUniform1i(p->loc_Texture_GammaRamps , sampler);sampler++;}
1198 if (p->loc_Texture_Normal >= 0) {p->tex_Texture_Normal = sampler;qglUniform1i(p->loc_Texture_Normal , sampler);sampler++;}
1199 if (p->loc_Texture_Color >= 0) {p->tex_Texture_Color = sampler;qglUniform1i(p->loc_Texture_Color , sampler);sampler++;}
1200 if (p->loc_Texture_Gloss >= 0) {p->tex_Texture_Gloss = sampler;qglUniform1i(p->loc_Texture_Gloss , sampler);sampler++;}
1201 if (p->loc_Texture_Glow >= 0) {p->tex_Texture_Glow = sampler;qglUniform1i(p->loc_Texture_Glow , sampler);sampler++;}
1202 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1203 if (p->loc_Texture_SecondaryColor >= 0) {p->tex_Texture_SecondaryColor = sampler;qglUniform1i(p->loc_Texture_SecondaryColor , sampler);sampler++;}
1204 if (p->loc_Texture_SecondaryGloss >= 0) {p->tex_Texture_SecondaryGloss = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss , sampler);sampler++;}
1205 if (p->loc_Texture_SecondaryGlow >= 0) {p->tex_Texture_SecondaryGlow = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow , sampler);sampler++;}
1206 if (p->loc_Texture_Pants >= 0) {p->tex_Texture_Pants = sampler;qglUniform1i(p->loc_Texture_Pants , sampler);sampler++;}
1207 if (p->loc_Texture_Shirt >= 0) {p->tex_Texture_Shirt = sampler;qglUniform1i(p->loc_Texture_Shirt , sampler);sampler++;}
1208 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1209 if (p->loc_Texture_FogMask >= 0) {p->tex_Texture_FogMask = sampler;qglUniform1i(p->loc_Texture_FogMask , sampler);sampler++;}
1210 if (p->loc_Texture_Lightmap >= 0) {p->tex_Texture_Lightmap = sampler;qglUniform1i(p->loc_Texture_Lightmap , sampler);sampler++;}
1211 if (p->loc_Texture_Deluxemap >= 0) {p->tex_Texture_Deluxemap = sampler;qglUniform1i(p->loc_Texture_Deluxemap , sampler);sampler++;}
1212 if (p->loc_Texture_Attenuation >= 0) {p->tex_Texture_Attenuation = sampler;qglUniform1i(p->loc_Texture_Attenuation , sampler);sampler++;}
1213 if (p->loc_Texture_Cube >= 0) {p->tex_Texture_Cube = sampler;qglUniform1i(p->loc_Texture_Cube , sampler);sampler++;}
1214 if (p->loc_Texture_Refraction >= 0) {p->tex_Texture_Refraction = sampler;qglUniform1i(p->loc_Texture_Refraction , sampler);sampler++;}
1215 if (p->loc_Texture_Reflection >= 0) {p->tex_Texture_Reflection = sampler;qglUniform1i(p->loc_Texture_Reflection , sampler);sampler++;}
1216 if (p->loc_Texture_ShadowMap2D >= 0) {p->tex_Texture_ShadowMap2D = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D , sampler);sampler++;}
1217 if (p->loc_Texture_CubeProjection >= 0) {p->tex_Texture_CubeProjection = sampler;qglUniform1i(p->loc_Texture_CubeProjection , sampler);sampler++;}
1218 if (p->loc_Texture_ScreenDepth >= 0) {p->tex_Texture_ScreenDepth = sampler;qglUniform1i(p->loc_Texture_ScreenDepth , sampler);sampler++;}
1219 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1220 if (p->loc_Texture_ScreenDiffuse >= 0) {p->tex_Texture_ScreenDiffuse = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse , sampler);sampler++;}
1221 if (p->loc_Texture_ScreenSpecular >= 0) {p->tex_Texture_ScreenSpecular = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular , sampler);sampler++;}
1222 if (p->loc_Texture_ReflectMask >= 0) {p->tex_Texture_ReflectMask = sampler;qglUniform1i(p->loc_Texture_ReflectMask , sampler);sampler++;}
1223 if (p->loc_Texture_ReflectCube >= 0) {p->tex_Texture_ReflectCube = sampler;qglUniform1i(p->loc_Texture_ReflectCube , sampler);sampler++;}
1224 if (p->loc_Texture_BounceGrid >= 0) {p->tex_Texture_BounceGrid = sampler;qglUniform1i(p->loc_Texture_BounceGrid , sampler);sampler++;}
1226 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1229 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
1233 Mem_Free(vertexstring);
1235 Mem_Free(geometrystring);
1237 Mem_Free(fragmentstring);
1240 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1242 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1243 if (r_glsl_permutation != perm)
1245 r_glsl_permutation = perm;
1246 if (!r_glsl_permutation->program)
1248 if (!r_glsl_permutation->compiled)
1249 R_GLSL_CompilePermutation(perm, mode, permutation);
1250 if (!r_glsl_permutation->program)
1252 // remove features until we find a valid permutation
1254 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1256 // reduce i more quickly whenever it would not remove any bits
1257 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1258 if (!(permutation & j))
1261 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1262 if (!r_glsl_permutation->compiled)
1263 R_GLSL_CompilePermutation(perm, mode, permutation);
1264 if (r_glsl_permutation->program)
1267 if (i >= SHADERPERMUTATION_COUNT)
1269 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1270 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1271 qglUseProgram(0);CHECKGLERROR
1272 return; // no bit left to clear, entire mode is broken
1277 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1279 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1280 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1281 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1288 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1289 extern D3DCAPS9 vid_d3d9caps;
1292 struct r_hlsl_permutation_s;
1293 typedef struct r_hlsl_permutation_s
1295 /// hash lookup data
1296 struct r_hlsl_permutation_s *hashnext;
1298 unsigned int permutation;
1300 /// indicates if we have tried compiling this permutation already
1302 /// NULL if compilation failed
1303 IDirect3DVertexShader9 *vertexshader;
1304 IDirect3DPixelShader9 *pixelshader;
1306 r_hlsl_permutation_t;
1308 typedef enum D3DVSREGISTER_e
1310 D3DVSREGISTER_TexMatrix = 0, // float4x4
1311 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1312 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1313 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1314 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1315 D3DVSREGISTER_ModelToLight = 20, // float4x4
1316 D3DVSREGISTER_EyePosition = 24,
1317 D3DVSREGISTER_FogPlane = 25,
1318 D3DVSREGISTER_LightDir = 26,
1319 D3DVSREGISTER_LightPosition = 27,
1323 typedef enum D3DPSREGISTER_e
1325 D3DPSREGISTER_Alpha = 0,
1326 D3DPSREGISTER_BloomBlur_Parameters = 1,
1327 D3DPSREGISTER_ClientTime = 2,
1328 D3DPSREGISTER_Color_Ambient = 3,
1329 D3DPSREGISTER_Color_Diffuse = 4,
1330 D3DPSREGISTER_Color_Specular = 5,
1331 D3DPSREGISTER_Color_Glow = 6,
1332 D3DPSREGISTER_Color_Pants = 7,
1333 D3DPSREGISTER_Color_Shirt = 8,
1334 D3DPSREGISTER_DeferredColor_Ambient = 9,
1335 D3DPSREGISTER_DeferredColor_Diffuse = 10,
1336 D3DPSREGISTER_DeferredColor_Specular = 11,
1337 D3DPSREGISTER_DeferredMod_Diffuse = 12,
1338 D3DPSREGISTER_DeferredMod_Specular = 13,
1339 D3DPSREGISTER_DistortScaleRefractReflect = 14,
1340 D3DPSREGISTER_EyePosition = 15, // unused
1341 D3DPSREGISTER_FogColor = 16,
1342 D3DPSREGISTER_FogHeightFade = 17,
1343 D3DPSREGISTER_FogPlane = 18,
1344 D3DPSREGISTER_FogPlaneViewDist = 19,
1345 D3DPSREGISTER_FogRangeRecip = 20,
1346 D3DPSREGISTER_LightColor = 21,
1347 D3DPSREGISTER_LightDir = 22, // unused
1348 D3DPSREGISTER_LightPosition = 23,
1349 D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1350 D3DPSREGISTER_PixelSize = 25,
1351 D3DPSREGISTER_ReflectColor = 26,
1352 D3DPSREGISTER_ReflectFactor = 27,
1353 D3DPSREGISTER_ReflectOffset = 28,
1354 D3DPSREGISTER_RefractColor = 29,
1355 D3DPSREGISTER_Saturation = 30,
1356 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1357 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1358 D3DPSREGISTER_ScreenToDepth = 33,
1359 D3DPSREGISTER_ShadowMap_Parameters = 34,
1360 D3DPSREGISTER_ShadowMap_TextureScale = 35,
1361 D3DPSREGISTER_SpecularPower = 36,
1362 D3DPSREGISTER_UserVec1 = 37,
1363 D3DPSREGISTER_UserVec2 = 38,
1364 D3DPSREGISTER_UserVec3 = 39,
1365 D3DPSREGISTER_UserVec4 = 40,
1366 D3DPSREGISTER_ViewTintColor = 41,
1367 D3DPSREGISTER_PixelToScreenTexCoord = 42,
1368 D3DPSREGISTER_BloomColorSubtract = 43,
1369 D3DPSREGISTER_ViewToLight = 44, // float4x4
1370 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1371 D3DPSREGISTER_NormalmapScrollBlend = 52,
1376 /// information about each possible shader permutation
1377 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1378 /// currently selected permutation
1379 r_hlsl_permutation_t *r_hlsl_permutation;
1380 /// storage for permutations linked in the hash table
1381 memexpandablearray_t r_hlsl_permutationarray;
1383 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1385 //unsigned int hashdepth = 0;
1386 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1387 r_hlsl_permutation_t *p;
1388 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1390 if (p->mode == mode && p->permutation == permutation)
1392 //if (hashdepth > 10)
1393 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1398 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1400 p->permutation = permutation;
1401 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1402 r_hlsl_permutationhash[mode][hashindex] = p;
1403 //if (hashdepth > 10)
1404 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1408 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1411 if (!filename || !filename[0])
1413 if (!strcmp(filename, "hlsl/default.hlsl"))
1415 if (!hlslshaderstring)
1417 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1418 if (hlslshaderstring)
1419 Con_DPrintf("Loading shaders from file %s...\n", filename);
1421 hlslshaderstring = (char *)builtinhlslshaderstring;
1423 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1424 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1425 return shaderstring;
1427 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1430 if (printfromdisknotice)
1431 Con_DPrintf("from disk %s... ", filename);
1432 return shaderstring;
1434 return shaderstring;
1438 //#include <d3dx9shader.h>
1439 //#include <d3dx9mesh.h>
1441 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1443 DWORD *vsbin = NULL;
1444 DWORD *psbin = NULL;
1445 fs_offset_t vsbinsize;
1446 fs_offset_t psbinsize;
1447 // IDirect3DVertexShader9 *vs = NULL;
1448 // IDirect3DPixelShader9 *ps = NULL;
1449 ID3DXBuffer *vslog = NULL;
1450 ID3DXBuffer *vsbuffer = NULL;
1451 ID3DXConstantTable *vsconstanttable = NULL;
1452 ID3DXBuffer *pslog = NULL;
1453 ID3DXBuffer *psbuffer = NULL;
1454 ID3DXConstantTable *psconstanttable = NULL;
1457 char temp[MAX_INPUTLINE];
1458 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1459 qboolean debugshader = gl_paranoid.integer != 0;
1460 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1461 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1464 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1465 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1467 if ((!vsbin && vertstring) || (!psbin && fragstring))
1469 const char* dllnames_d3dx9 [] =
1493 dllhandle_t d3dx9_dll = NULL;
1494 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1495 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1496 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1497 dllfunction_t d3dx9_dllfuncs[] =
1499 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
1500 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
1501 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
1504 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1506 DWORD shaderflags = 0;
1508 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1509 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1510 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1511 if (vertstring && vertstring[0])
1515 // vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1516 // FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1517 FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1518 vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1521 vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1524 vsbinsize = vsbuffer->GetBufferSize();
1525 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1526 memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1527 vsbuffer->Release();
1531 strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1532 Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1536 if (fragstring && fragstring[0])
1540 // psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1541 // FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1542 FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1543 psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1546 psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1549 psbinsize = psbuffer->GetBufferSize();
1550 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1551 memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1552 psbuffer->Release();
1556 strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1557 Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1561 Sys_UnloadLibrary(&d3dx9_dll);
1564 Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1568 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1569 if (FAILED(vsresult))
1570 Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1571 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1572 if (FAILED(psresult))
1573 Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1575 // free the shader data
1576 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1577 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1580 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1583 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1584 int vertstring_length = 0;
1585 int geomstring_length = 0;
1586 int fragstring_length = 0;
1588 char *vertexstring, *geometrystring, *fragmentstring;
1589 char *vertstring, *geomstring, *fragstring;
1590 char permutationname[256];
1591 char cachename[256];
1592 int vertstrings_count = 0;
1593 int geomstrings_count = 0;
1594 int fragstrings_count = 0;
1595 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1596 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1597 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1602 p->vertexshader = NULL;
1603 p->pixelshader = NULL;
1605 permutationname[0] = 0;
1607 vertexstring = R_HLSL_GetText(modeinfo->vertexfilename, true);
1608 geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1609 fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1611 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1612 strlcat(cachename, "hlsl/", sizeof(cachename));
1614 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1615 vertstrings_count = 0;
1616 geomstrings_count = 0;
1617 fragstrings_count = 0;
1618 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1619 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1620 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1622 // the first pretext is which type of shader to compile as
1623 // (later these will all be bound together as a program object)
1624 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1625 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1626 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1628 // the second pretext is the mode (for example a light source)
1629 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1630 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1631 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1632 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1633 strlcat(cachename, modeinfo->name, sizeof(cachename));
1635 // now add all the permutation pretexts
1636 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1638 if (permutation & (1<<i))
1640 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1641 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1642 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1643 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1644 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1648 // keep line numbers correct
1649 vertstrings_list[vertstrings_count++] = "\n";
1650 geomstrings_list[geomstrings_count++] = "\n";
1651 fragstrings_list[fragstrings_count++] = "\n";
1656 R_CompileShader_AddStaticParms(mode, permutation);
1657 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1658 vertstrings_count += shaderstaticparms_count;
1659 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1660 geomstrings_count += shaderstaticparms_count;
1661 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1662 fragstrings_count += shaderstaticparms_count;
1664 // replace spaces in the cachename with _ characters
1665 for (i = 0;cachename[i];i++)
1666 if (cachename[i] == ' ')
1669 // now append the shader text itself
1670 vertstrings_list[vertstrings_count++] = vertexstring;
1671 geomstrings_list[geomstrings_count++] = geometrystring;
1672 fragstrings_list[fragstrings_count++] = fragmentstring;
1674 // if any sources were NULL, clear the respective list
1676 vertstrings_count = 0;
1677 if (!geometrystring)
1678 geomstrings_count = 0;
1679 if (!fragmentstring)
1680 fragstrings_count = 0;
1682 vertstring_length = 0;
1683 for (i = 0;i < vertstrings_count;i++)
1684 vertstring_length += strlen(vertstrings_list[i]);
1685 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1686 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1687 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1689 geomstring_length = 0;
1690 for (i = 0;i < geomstrings_count;i++)
1691 geomstring_length += strlen(geomstrings_list[i]);
1692 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1693 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1694 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1696 fragstring_length = 0;
1697 for (i = 0;i < fragstrings_count;i++)
1698 fragstring_length += strlen(fragstrings_list[i]);
1699 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1700 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1701 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1703 // try to load the cached shader, or generate one
1704 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1706 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1707 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1709 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
1713 Mem_Free(vertstring);
1715 Mem_Free(geomstring);
1717 Mem_Free(fragstring);
1719 Mem_Free(vertexstring);
1721 Mem_Free(geometrystring);
1723 Mem_Free(fragmentstring);
1726 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1727 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1728 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);}
1729 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);}
1730 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);}
1731 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);}
1733 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1734 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1735 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);}
1736 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);}
1737 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);}
1738 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);}
1740 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1742 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1743 if (r_hlsl_permutation != perm)
1745 r_hlsl_permutation = perm;
1746 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1748 if (!r_hlsl_permutation->compiled)
1749 R_HLSL_CompilePermutation(perm, mode, permutation);
1750 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1752 // remove features until we find a valid permutation
1754 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1756 // reduce i more quickly whenever it would not remove any bits
1757 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1758 if (!(permutation & j))
1761 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1762 if (!r_hlsl_permutation->compiled)
1763 R_HLSL_CompilePermutation(perm, mode, permutation);
1764 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1767 if (i >= SHADERPERMUTATION_COUNT)
1769 //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1770 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1771 return; // no bit left to clear, entire mode is broken
1775 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1776 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1778 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1779 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1780 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1784 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1786 DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1787 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1788 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1789 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1792 void R_GLSL_Restart_f(void)
1794 unsigned int i, limit;
1795 if (glslshaderstring && glslshaderstring != builtinshaderstring)
1796 Mem_Free(glslshaderstring);
1797 glslshaderstring = NULL;
1798 if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1799 Mem_Free(hlslshaderstring);
1800 hlslshaderstring = NULL;
1801 switch(vid.renderpath)
1803 case RENDERPATH_D3D9:
1806 r_hlsl_permutation_t *p;
1807 r_hlsl_permutation = NULL;
1808 limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1809 for (i = 0;i < limit;i++)
1811 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1813 if (p->vertexshader)
1814 IDirect3DVertexShader9_Release(p->vertexshader);
1816 IDirect3DPixelShader9_Release(p->pixelshader);
1817 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1820 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1824 case RENDERPATH_D3D10:
1825 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1827 case RENDERPATH_D3D11:
1828 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1830 case RENDERPATH_GL20:
1831 case RENDERPATH_GLES2:
1833 r_glsl_permutation_t *p;
1834 r_glsl_permutation = NULL;
1835 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1836 for (i = 0;i < limit;i++)
1838 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1840 GL_Backend_FreeProgram(p->program);
1841 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1844 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1847 case RENDERPATH_GL11:
1848 case RENDERPATH_GL13:
1849 case RENDERPATH_GLES1:
1851 case RENDERPATH_SOFT:
1856 void R_GLSL_DumpShader_f(void)
1861 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1864 FS_Print(file, "/* The engine may define the following macros:\n");
1865 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1866 for (i = 0;i < SHADERMODE_COUNT;i++)
1867 FS_Print(file, glslshadermodeinfo[i].pretext);
1868 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1869 FS_Print(file, shaderpermutationinfo[i].pretext);
1870 FS_Print(file, "*/\n");
1871 FS_Print(file, builtinshaderstring);
1873 Con_Printf("glsl/default.glsl written\n");
1876 Con_Printf("failed to write to glsl/default.glsl\n");
1878 file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1881 FS_Print(file, "/* The engine may define the following macros:\n");
1882 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1883 for (i = 0;i < SHADERMODE_COUNT;i++)
1884 FS_Print(file, hlslshadermodeinfo[i].pretext);
1885 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1886 FS_Print(file, shaderpermutationinfo[i].pretext);
1887 FS_Print(file, "*/\n");
1888 FS_Print(file, builtinhlslshaderstring);
1890 Con_Printf("hlsl/default.hlsl written\n");
1893 Con_Printf("failed to write to hlsl/default.hlsl\n");
1896 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean notrippy)
1898 unsigned int permutation = 0;
1899 if (r_trippy.integer && !notrippy)
1900 permutation |= SHADERPERMUTATION_TRIPPY;
1901 permutation |= SHADERPERMUTATION_VIEWTINT;
1903 permutation |= SHADERPERMUTATION_DIFFUSE;
1905 permutation |= SHADERPERMUTATION_SPECULAR;
1906 if (texturemode == GL_MODULATE)
1907 permutation |= SHADERPERMUTATION_COLORMAPPING;
1908 else if (texturemode == GL_ADD)
1909 permutation |= SHADERPERMUTATION_GLOW;
1910 else if (texturemode == GL_DECAL)
1911 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1913 texturemode = GL_MODULATE;
1914 GL_AlphaToCoverage(false);
1915 switch (vid.renderpath)
1917 case RENDERPATH_D3D9:
1919 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1920 R_Mesh_TexBind(GL20TU_FIRST , first );
1921 R_Mesh_TexBind(GL20TU_SECOND, second);
1924 case RENDERPATH_D3D10:
1925 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1927 case RENDERPATH_D3D11:
1928 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1930 case RENDERPATH_GL20:
1931 case RENDERPATH_GLES2:
1932 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
1933 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1934 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1936 case RENDERPATH_GL13:
1937 case RENDERPATH_GLES1:
1938 R_Mesh_TexBind(0, first );
1939 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1940 R_Mesh_TexBind(1, second);
1942 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1944 case RENDERPATH_GL11:
1945 R_Mesh_TexBind(0, first );
1947 case RENDERPATH_SOFT:
1948 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
1949 R_Mesh_TexBind(GL20TU_FIRST , first );
1950 R_Mesh_TexBind(GL20TU_SECOND, second);
1955 void R_SetupShader_DepthOrShadow(qboolean notrippy)
1957 unsigned int permutation = 0;
1958 if (r_trippy.integer && !notrippy)
1959 permutation |= SHADERPERMUTATION_TRIPPY;
1960 GL_AlphaToCoverage(false);
1961 switch (vid.renderpath)
1963 case RENDERPATH_D3D9:
1965 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1968 case RENDERPATH_D3D10:
1969 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1971 case RENDERPATH_D3D11:
1972 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1974 case RENDERPATH_GL20:
1975 case RENDERPATH_GLES2:
1976 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1978 case RENDERPATH_GL13:
1979 case RENDERPATH_GLES1:
1980 R_Mesh_TexBind(0, 0);
1981 R_Mesh_TexBind(1, 0);
1983 case RENDERPATH_GL11:
1984 R_Mesh_TexBind(0, 0);
1986 case RENDERPATH_SOFT:
1987 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1992 void R_SetupShader_ShowDepth(qboolean notrippy)
1994 int permutation = 0;
1995 if (r_trippy.integer && !notrippy)
1996 permutation |= SHADERPERMUTATION_TRIPPY;
1997 if (r_trippy.integer)
1998 permutation |= SHADERPERMUTATION_TRIPPY;
1999 GL_AlphaToCoverage(false);
2000 switch (vid.renderpath)
2002 case RENDERPATH_D3D9:
2004 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, permutation);
2007 case RENDERPATH_D3D10:
2008 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2010 case RENDERPATH_D3D11:
2011 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2013 case RENDERPATH_GL20:
2014 case RENDERPATH_GLES2:
2015 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, permutation);
2017 case RENDERPATH_GL13:
2018 case RENDERPATH_GLES1:
2020 case RENDERPATH_GL11:
2022 case RENDERPATH_SOFT:
2023 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, permutation);
2028 extern qboolean r_shadow_usingdeferredprepass;
2029 extern cvar_t r_shadow_deferred_8bitrange;
2030 extern rtexture_t *r_shadow_attenuationgradienttexture;
2031 extern rtexture_t *r_shadow_attenuation2dtexture;
2032 extern rtexture_t *r_shadow_attenuation3dtexture;
2033 extern qboolean r_shadow_usingshadowmap2d;
2034 extern qboolean r_shadow_usingshadowmaportho;
2035 extern float r_shadow_shadowmap_texturescale[2];
2036 extern float r_shadow_shadowmap_parameters[4];
2037 extern qboolean r_shadow_shadowmapvsdct;
2038 extern qboolean r_shadow_shadowmapsampler;
2039 extern int r_shadow_shadowmappcf;
2040 extern rtexture_t *r_shadow_shadowmap2dtexture;
2041 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2042 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2043 extern matrix4x4_t r_shadow_shadowmapmatrix;
2044 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2045 extern int r_shadow_prepass_width;
2046 extern int r_shadow_prepass_height;
2047 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2048 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2049 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2050 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2051 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2053 #define BLENDFUNC_ALLOWS_COLORMOD 1
2054 #define BLENDFUNC_ALLOWS_FOG 2
2055 #define BLENDFUNC_ALLOWS_FOG_HACK0 4
2056 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2057 #define BLENDFUNC_ALLOWS_ANYFOG (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2058 static int R_BlendFuncFlags(int src, int dst)
2062 // a blendfunc allows colormod if:
2063 // a) it can never keep the destination pixel invariant, or
2064 // b) it can keep the destination pixel invariant, and still can do so if colormodded
2065 // this is to prevent unintended side effects from colormod
2067 // a blendfunc allows fog if:
2068 // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2069 // this is to prevent unintended side effects from fog
2071 // these checks are the output of fogeval.pl
2073 r |= BLENDFUNC_ALLOWS_COLORMOD;
2074 if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2075 if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2076 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2077 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2078 if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2079 if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2080 if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2081 if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2082 if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2083 if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2084 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2085 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2086 if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2087 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2088 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2089 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2090 if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2091 if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2092 if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2093 if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2094 if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2099 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, qboolean notrippy)
2101 // select a permutation of the lighting shader appropriate to this
2102 // combination of texture, entity, light source, and fogging, only use the
2103 // minimum features necessary to avoid wasting rendering time in the
2104 // fragment shader on features that are not being used
2105 unsigned int permutation = 0;
2106 unsigned int mode = 0;
2108 static float dummy_colormod[3] = {1, 1, 1};
2109 float *colormod = rsurface.colormod;
2111 matrix4x4_t tempmatrix;
2112 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2113 if (r_trippy.integer && !notrippy)
2114 permutation |= SHADERPERMUTATION_TRIPPY;
2115 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2116 permutation |= SHADERPERMUTATION_ALPHAKILL;
2117 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2118 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2119 if (rsurfacepass == RSURFPASS_BACKGROUND)
2121 // distorted background
2122 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2124 mode = SHADERMODE_WATER;
2125 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2127 // this is the right thing to do for wateralpha
2128 GL_BlendFunc(GL_ONE, GL_ZERO);
2129 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2133 // this is the right thing to do for entity alpha
2134 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2135 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2138 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2140 mode = SHADERMODE_REFRACTION;
2141 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2142 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2146 mode = SHADERMODE_GENERIC;
2147 permutation |= SHADERPERMUTATION_DIFFUSE;
2148 GL_BlendFunc(GL_ONE, GL_ZERO);
2149 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2151 GL_AlphaToCoverage(false);
2153 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2155 if (r_glsl_offsetmapping.integer)
2157 switch(rsurface.texture->offsetmapping)
2159 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2160 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2161 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2162 case OFFSETMAPPING_OFF: break;
2165 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2166 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2167 // normalmap (deferred prepass), may use alpha test on diffuse
2168 mode = SHADERMODE_DEFERREDGEOMETRY;
2169 GL_BlendFunc(GL_ONE, GL_ZERO);
2170 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2171 GL_AlphaToCoverage(false);
2173 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2175 if (r_glsl_offsetmapping.integer)
2177 switch(rsurface.texture->offsetmapping)
2179 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2180 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2181 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2182 case OFFSETMAPPING_OFF: break;
2185 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2186 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2188 mode = SHADERMODE_LIGHTSOURCE;
2189 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2190 permutation |= SHADERPERMUTATION_CUBEFILTER;
2191 if (diffusescale > 0)
2192 permutation |= SHADERPERMUTATION_DIFFUSE;
2193 if (specularscale > 0)
2194 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2195 if (r_refdef.fogenabled)
2196 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2197 if (rsurface.texture->colormapping)
2198 permutation |= SHADERPERMUTATION_COLORMAPPING;
2199 if (r_shadow_usingshadowmap2d)
2201 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2202 if(r_shadow_shadowmapvsdct)
2203 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2205 if (r_shadow_shadowmapsampler)
2206 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2207 if (r_shadow_shadowmappcf > 1)
2208 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2209 else if (r_shadow_shadowmappcf)
2210 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2212 if (rsurface.texture->reflectmasktexture)
2213 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2214 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2215 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2216 GL_AlphaToCoverage(false);
2218 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2220 if (r_glsl_offsetmapping.integer)
2222 switch(rsurface.texture->offsetmapping)
2224 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2225 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2226 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2227 case OFFSETMAPPING_OFF: break;
2230 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2231 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2232 // unshaded geometry (fullbright or ambient model lighting)
2233 mode = SHADERMODE_FLATCOLOR;
2234 ambientscale = diffusescale = specularscale = 0;
2235 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2236 permutation |= SHADERPERMUTATION_GLOW;
2237 if (r_refdef.fogenabled)
2238 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2239 if (rsurface.texture->colormapping)
2240 permutation |= SHADERPERMUTATION_COLORMAPPING;
2241 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2243 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2244 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2246 if (r_shadow_shadowmapsampler)
2247 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2248 if (r_shadow_shadowmappcf > 1)
2249 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2250 else if (r_shadow_shadowmappcf)
2251 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2253 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2254 permutation |= SHADERPERMUTATION_REFLECTION;
2255 if (rsurface.texture->reflectmasktexture)
2256 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2257 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2258 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2259 GL_AlphaToCoverage(r_transparent_alphatocoverage.integer && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
2261 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2263 if (r_glsl_offsetmapping.integer)
2265 switch(rsurface.texture->offsetmapping)
2267 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2268 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2269 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2270 case OFFSETMAPPING_OFF: break;
2273 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2274 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2275 // directional model lighting
2276 mode = SHADERMODE_LIGHTDIRECTION;
2277 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2278 permutation |= SHADERPERMUTATION_GLOW;
2279 permutation |= SHADERPERMUTATION_DIFFUSE;
2280 if (specularscale > 0)
2281 permutation |= SHADERPERMUTATION_SPECULAR;
2282 if (r_refdef.fogenabled)
2283 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2284 if (rsurface.texture->colormapping)
2285 permutation |= SHADERPERMUTATION_COLORMAPPING;
2286 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2288 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2289 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2291 if (r_shadow_shadowmapsampler)
2292 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2293 if (r_shadow_shadowmappcf > 1)
2294 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2295 else if (r_shadow_shadowmappcf)
2296 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2298 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2299 permutation |= SHADERPERMUTATION_REFLECTION;
2300 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2301 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2302 if (rsurface.texture->reflectmasktexture)
2303 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2304 if (r_shadow_bouncegridtexture)
2306 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2307 if (r_shadow_bouncegriddirectional)
2308 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2310 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2311 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2312 GL_AlphaToCoverage(r_transparent_alphatocoverage.integer && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
2314 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2316 if (r_glsl_offsetmapping.integer)
2318 switch(rsurface.texture->offsetmapping)
2320 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2321 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2322 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2323 case OFFSETMAPPING_OFF: break;
2326 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2327 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2328 // ambient model lighting
2329 mode = SHADERMODE_LIGHTDIRECTION;
2330 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2331 permutation |= SHADERPERMUTATION_GLOW;
2332 if (r_refdef.fogenabled)
2333 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2334 if (rsurface.texture->colormapping)
2335 permutation |= SHADERPERMUTATION_COLORMAPPING;
2336 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2338 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2339 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2341 if (r_shadow_shadowmapsampler)
2342 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2343 if (r_shadow_shadowmappcf > 1)
2344 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2345 else if (r_shadow_shadowmappcf)
2346 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2348 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2349 permutation |= SHADERPERMUTATION_REFLECTION;
2350 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2351 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2352 if (rsurface.texture->reflectmasktexture)
2353 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2354 if (r_shadow_bouncegridtexture)
2356 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2357 if (r_shadow_bouncegriddirectional)
2358 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2360 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2361 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2362 GL_AlphaToCoverage(r_transparent_alphatocoverage.integer && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
2366 if (r_glsl_offsetmapping.integer)
2368 switch(rsurface.texture->offsetmapping)
2370 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2371 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2372 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2373 case OFFSETMAPPING_OFF: break;
2376 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2377 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2379 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2380 permutation |= SHADERPERMUTATION_GLOW;
2381 if (r_refdef.fogenabled)
2382 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2383 if (rsurface.texture->colormapping)
2384 permutation |= SHADERPERMUTATION_COLORMAPPING;
2385 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2387 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2388 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2390 if (r_shadow_shadowmapsampler)
2391 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2392 if (r_shadow_shadowmappcf > 1)
2393 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2394 else if (r_shadow_shadowmappcf)
2395 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2397 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2398 permutation |= SHADERPERMUTATION_REFLECTION;
2399 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2400 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2401 if (rsurface.texture->reflectmasktexture)
2402 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2403 if (FAKELIGHT_ENABLED)
2405 // fake lightmapping (q1bsp, q3bsp, fullbright map)
2406 mode = SHADERMODE_FAKELIGHT;
2407 permutation |= SHADERPERMUTATION_DIFFUSE;
2408 if (specularscale > 0)
2409 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2411 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2413 // deluxemapping (light direction texture)
2414 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2415 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2417 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2418 permutation |= SHADERPERMUTATION_DIFFUSE;
2419 if (specularscale > 0)
2420 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2422 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2424 // fake deluxemapping (uniform light direction in tangentspace)
2425 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2426 permutation |= SHADERPERMUTATION_DIFFUSE;
2427 if (specularscale > 0)
2428 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2430 else if (rsurface.uselightmaptexture)
2432 // ordinary lightmapping (q1bsp, q3bsp)
2433 mode = SHADERMODE_LIGHTMAP;
2437 // ordinary vertex coloring (q3bsp)
2438 mode = SHADERMODE_VERTEXCOLOR;
2440 if (r_shadow_bouncegridtexture)
2442 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2443 if (r_shadow_bouncegriddirectional)
2444 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2446 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2447 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2448 GL_AlphaToCoverage(r_transparent_alphatocoverage.integer && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
2450 if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2451 colormod = dummy_colormod;
2452 if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2453 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2454 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2455 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2456 switch(vid.renderpath)
2458 case RENDERPATH_D3D9:
2460 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);
2461 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2462 R_SetupShader_SetPermutationHLSL(mode, permutation);
2463 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2464 if (mode == SHADERMODE_LIGHTSOURCE)
2466 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2467 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2471 if (mode == SHADERMODE_LIGHTDIRECTION)
2473 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2476 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2477 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2478 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2479 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2480 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2482 if (mode == SHADERMODE_LIGHTSOURCE)
2484 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2485 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2486 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2487 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2488 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2490 // additive passes are only darkened by fog, not tinted
2491 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2492 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2496 if (mode == SHADERMODE_FLATCOLOR)
2498 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2500 else if (mode == SHADERMODE_LIGHTDIRECTION)
2502 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]);
2503 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2504 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);
2505 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);
2506 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2507 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2508 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2512 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2513 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2514 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);
2515 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);
2516 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2518 // additive passes are only darkened by fog, not tinted
2519 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2520 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2522 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2523 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);
2524 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2525 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2526 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2527 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2528 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2529 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2530 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2531 if (mode == SHADERMODE_WATER)
2532 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2534 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2535 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2536 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2537 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));
2538 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2539 if (rsurface.texture->pantstexture)
2540 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2542 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2543 if (rsurface.texture->shirttexture)
2544 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2546 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2547 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2548 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2549 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2550 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2551 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2552 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2553 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2554 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2555 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2557 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2558 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2560 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2561 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2562 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2563 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2564 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2565 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2566 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2567 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2568 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2569 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2570 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2571 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2572 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2573 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2574 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2575 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2576 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2577 if (rsurfacepass == RSURFPASS_BACKGROUND)
2579 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2580 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2581 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2585 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2587 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2588 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2589 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2590 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2591 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2593 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2594 if (rsurface.rtlight)
2596 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2597 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2602 case RENDERPATH_D3D10:
2603 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2605 case RENDERPATH_D3D11:
2606 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2608 case RENDERPATH_GL20:
2609 case RENDERPATH_GLES2:
2610 if (!vid.useinterleavedarrays)
2612 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);
2613 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2614 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2615 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2616 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2617 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2618 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2619 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2623 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);
2624 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2626 R_SetupShader_SetPermutationGLSL(mode, permutation);
2627 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2628 if (mode == SHADERMODE_LIGHTSOURCE)
2630 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2631 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2632 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2633 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2634 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2635 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);
2637 // additive passes are only darkened by fog, not tinted
2638 if (r_glsl_permutation->loc_FogColor >= 0)
2639 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2640 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2644 if (mode == SHADERMODE_FLATCOLOR)
2646 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2648 else if (mode == SHADERMODE_LIGHTDIRECTION)
2650 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]);
2651 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]);
2652 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);
2653 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);
2654 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);
2655 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]);
2656 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]);
2660 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]);
2661 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]);
2662 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);
2663 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);
2664 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);
2666 // additive passes are only darkened by fog, not tinted
2667 if (r_glsl_permutation->loc_FogColor >= 0)
2669 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2670 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2672 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2674 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);
2675 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]);
2676 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]);
2677 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]);
2678 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]);
2679 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2680 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2681 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2682 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]);
2684 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2685 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2686 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2687 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]);
2688 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]);
2690 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2691 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));
2692 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2693 if (r_glsl_permutation->loc_Color_Pants >= 0)
2695 if (rsurface.texture->pantstexture)
2696 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2698 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2700 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2702 if (rsurface.texture->shirttexture)
2703 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2705 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2707 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]);
2708 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2709 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2710 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2711 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2712 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2713 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2714 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2715 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2717 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]);
2718 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2719 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);}
2720 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2722 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
2723 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
2724 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
2725 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
2726 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
2727 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
2728 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
2729 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
2730 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
2731 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
2732 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
2733 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
2734 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
2735 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
2736 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);
2737 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
2738 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
2739 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2740 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2741 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2742 if (rsurfacepass == RSURFPASS_BACKGROUND)
2744 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);
2745 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);
2746 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);
2750 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);
2752 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2753 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2754 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
2755 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
2756 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2758 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture );
2759 if (rsurface.rtlight)
2761 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2762 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2765 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2768 case RENDERPATH_GL11:
2769 case RENDERPATH_GL13:
2770 case RENDERPATH_GLES1:
2772 case RENDERPATH_SOFT:
2773 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);
2774 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2775 R_SetupShader_SetPermutationSoft(mode, permutation);
2776 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2777 if (mode == SHADERMODE_LIGHTSOURCE)
2779 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2780 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2781 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2782 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2783 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2784 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2786 // additive passes are only darkened by fog, not tinted
2787 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2788 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2792 if (mode == SHADERMODE_FLATCOLOR)
2794 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2796 else if (mode == SHADERMODE_LIGHTDIRECTION)
2798 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]);
2799 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2800 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);
2801 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);
2802 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2803 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]);
2804 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2808 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2809 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2810 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);
2811 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);
2812 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2814 // additive passes are only darkened by fog, not tinted
2815 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2816 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2818 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2819 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);
2820 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2821 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2822 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]);
2823 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]);
2824 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2825 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2826 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2827 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2829 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2830 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2831 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2832 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2833 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]);
2835 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2836 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));
2837 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2838 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2840 if (rsurface.texture->pantstexture)
2841 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2843 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2845 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2847 if (rsurface.texture->shirttexture)
2848 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2850 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2852 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2853 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2854 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2855 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2856 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2857 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2858 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2859 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2860 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2862 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2863 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2865 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2866 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2867 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2868 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2869 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2870 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2871 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2872 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2873 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2874 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2875 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2876 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2877 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2878 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2879 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2880 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2881 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2882 if (rsurfacepass == RSURFPASS_BACKGROUND)
2884 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2885 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2886 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2890 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2892 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2893 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2894 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2895 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2896 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2898 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2899 if (rsurface.rtlight)
2901 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2902 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2909 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2911 // select a permutation of the lighting shader appropriate to this
2912 // combination of texture, entity, light source, and fogging, only use the
2913 // minimum features necessary to avoid wasting rendering time in the
2914 // fragment shader on features that are not being used
2915 unsigned int permutation = 0;
2916 unsigned int mode = 0;
2917 const float *lightcolorbase = rtlight->currentcolor;
2918 float ambientscale = rtlight->ambientscale;
2919 float diffusescale = rtlight->diffusescale;
2920 float specularscale = rtlight->specularscale;
2921 // this is the location of the light in view space
2922 vec3_t viewlightorigin;
2923 // this transforms from view space (camera) to light space (cubemap)
2924 matrix4x4_t viewtolight;
2925 matrix4x4_t lighttoview;
2926 float viewtolight16f[16];
2927 float range = 1.0f / r_shadow_deferred_8bitrange.value;
2929 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2930 if (rtlight->currentcubemap != r_texture_whitecube)
2931 permutation |= SHADERPERMUTATION_CUBEFILTER;
2932 if (diffusescale > 0)
2933 permutation |= SHADERPERMUTATION_DIFFUSE;
2934 if (specularscale > 0 && r_shadow_gloss.integer > 0)
2935 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2936 if (r_shadow_usingshadowmap2d)
2938 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2939 if (r_shadow_shadowmapvsdct)
2940 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2942 if (r_shadow_shadowmapsampler)
2943 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2944 if (r_shadow_shadowmappcf > 1)
2945 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2946 else if (r_shadow_shadowmappcf)
2947 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2949 GL_AlphaToCoverage(false);
2950 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2951 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2952 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2953 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2954 switch(vid.renderpath)
2956 case RENDERPATH_D3D9:
2958 R_SetupShader_SetPermutationHLSL(mode, permutation);
2959 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2960 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
2961 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2962 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2963 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2964 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2965 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2966 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2967 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2968 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2970 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2971 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthcolortexture );
2972 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2973 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2974 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dcolortexture );
2975 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2978 case RENDERPATH_D3D10:
2979 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2981 case RENDERPATH_D3D11:
2982 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2984 case RENDERPATH_GL20:
2985 case RENDERPATH_GLES2:
2986 R_SetupShader_SetPermutationGLSL(mode, permutation);
2987 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2988 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
2989 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);
2990 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);
2991 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);
2992 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]);
2993 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]);
2994 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));
2995 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]);
2996 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
2998 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2999 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
3000 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
3001 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
3002 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );
3003 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
3005 case RENDERPATH_GL11:
3006 case RENDERPATH_GL13:
3007 case RENDERPATH_GLES1:
3009 case RENDERPATH_SOFT:
3010 R_SetupShader_SetPermutationGLSL(mode, permutation);
3011 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3012 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
3013 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
3014 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
3015 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3016 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3017 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]);
3018 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));
3019 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3020 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3022 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3023 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
3024 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3025 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3026 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
3027 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3032 #define SKINFRAME_HASH 1024
3036 int loadsequence; // incremented each level change
3037 memexpandablearray_t array;
3038 skinframe_t *hash[SKINFRAME_HASH];
3041 r_skinframe_t r_skinframe;
3043 void R_SkinFrame_PrepareForPurge(void)
3045 r_skinframe.loadsequence++;
3046 // wrap it without hitting zero
3047 if (r_skinframe.loadsequence >= 200)
3048 r_skinframe.loadsequence = 1;
3051 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3055 // mark the skinframe as used for the purging code
3056 skinframe->loadsequence = r_skinframe.loadsequence;
3059 void R_SkinFrame_Purge(void)
3063 for (i = 0;i < SKINFRAME_HASH;i++)
3065 for (s = r_skinframe.hash[i];s;s = s->next)
3067 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3069 if (s->merged == s->base)
3071 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3072 R_PurgeTexture(s->stain );s->stain = NULL;
3073 R_PurgeTexture(s->merged);s->merged = NULL;
3074 R_PurgeTexture(s->base );s->base = NULL;
3075 R_PurgeTexture(s->pants );s->pants = NULL;
3076 R_PurgeTexture(s->shirt );s->shirt = NULL;
3077 R_PurgeTexture(s->nmap );s->nmap = NULL;
3078 R_PurgeTexture(s->gloss );s->gloss = NULL;
3079 R_PurgeTexture(s->glow );s->glow = NULL;
3080 R_PurgeTexture(s->fog );s->fog = NULL;
3081 R_PurgeTexture(s->reflect);s->reflect = NULL;
3082 s->loadsequence = 0;
3088 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3090 char basename[MAX_QPATH];
3092 Image_StripImageExtension(name, basename, sizeof(basename));
3094 if( last == NULL ) {
3096 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3097 item = r_skinframe.hash[hashindex];
3102 // linearly search through the hash bucket
3103 for( ; item ; item = item->next ) {
3104 if( !strcmp( item->basename, basename ) ) {
3111 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3115 char basename[MAX_QPATH];
3117 Image_StripImageExtension(name, basename, sizeof(basename));
3119 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3120 for (item = r_skinframe.hash[hashindex];item;item = item->next)
3121 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3125 rtexture_t *dyntexture;
3126 // check whether its a dynamic texture
3127 dyntexture = CL_GetDynTexture( basename );
3128 if (!add && !dyntexture)
3130 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3131 memset(item, 0, sizeof(*item));
3132 strlcpy(item->basename, basename, sizeof(item->basename));
3133 item->base = dyntexture; // either NULL or dyntexture handle
3134 item->textureflags = textureflags;
3135 item->comparewidth = comparewidth;
3136 item->compareheight = compareheight;
3137 item->comparecrc = comparecrc;
3138 item->next = r_skinframe.hash[hashindex];
3139 r_skinframe.hash[hashindex] = item;
3141 else if( item->base == NULL )
3143 rtexture_t *dyntexture;
3144 // check whether its a dynamic texture
3145 // 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]
3146 dyntexture = CL_GetDynTexture( basename );
3147 item->base = dyntexture; // either NULL or dyntexture handle
3150 R_SkinFrame_MarkUsed(item);
3154 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3156 unsigned long long avgcolor[5], wsum; \
3164 for(pix = 0; pix < cnt; ++pix) \
3167 for(comp = 0; comp < 3; ++comp) \
3169 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3172 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3174 for(comp = 0; comp < 3; ++comp) \
3175 avgcolor[comp] += getpixel * w; \
3178 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3179 avgcolor[4] += getpixel; \
3181 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3183 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3184 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3185 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3186 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3189 extern cvar_t gl_picmip;
3190 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3193 unsigned char *pixels;
3194 unsigned char *bumppixels;
3195 unsigned char *basepixels = NULL;
3196 int basepixels_width = 0;
3197 int basepixels_height = 0;
3198 skinframe_t *skinframe;
3199 rtexture_t *ddsbase = NULL;
3200 qboolean ddshasalpha = false;
3201 float ddsavgcolor[4];
3202 char basename[MAX_QPATH];
3203 int miplevel = R_PicmipForFlags(textureflags);
3204 int savemiplevel = miplevel;
3207 if (cls.state == ca_dedicated)
3210 // return an existing skinframe if already loaded
3211 // if loading of the first image fails, don't make a new skinframe as it
3212 // would cause all future lookups of this to be missing
3213 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3214 if (skinframe && skinframe->base)
3217 Image_StripImageExtension(name, basename, sizeof(basename));
3219 // check for DDS texture file first
3220 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3222 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3223 if (basepixels == NULL)
3227 // FIXME handle miplevel
3229 if (developer_loading.integer)
3230 Con_Printf("loading skin \"%s\"\n", name);
3232 // we've got some pixels to store, so really allocate this new texture now
3234 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3235 skinframe->stain = NULL;
3236 skinframe->merged = NULL;
3237 skinframe->base = NULL;
3238 skinframe->pants = NULL;
3239 skinframe->shirt = NULL;
3240 skinframe->nmap = NULL;
3241 skinframe->gloss = NULL;
3242 skinframe->glow = NULL;
3243 skinframe->fog = NULL;
3244 skinframe->reflect = NULL;
3245 skinframe->hasalpha = false;
3249 skinframe->base = ddsbase;
3250 skinframe->hasalpha = ddshasalpha;
3251 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3252 if (r_loadfog && skinframe->hasalpha)
3253 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3254 //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]);
3258 basepixels_width = image_width;
3259 basepixels_height = image_height;
3260 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3261 if (textureflags & TEXF_ALPHA)
3263 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3265 if (basepixels[j] < 255)
3267 skinframe->hasalpha = true;
3271 if (r_loadfog && skinframe->hasalpha)
3273 // has transparent pixels
3274 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3275 for (j = 0;j < image_width * image_height * 4;j += 4)
3280 pixels[j+3] = basepixels[j+3];
3282 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3286 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3287 //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]);
3288 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3289 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3290 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3291 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3296 mymiplevel = savemiplevel;
3297 if (r_loadnormalmap)
3298 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);
3299 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3301 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3302 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3303 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3304 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3307 // _norm is the name used by tenebrae and has been adopted as standard
3308 if (r_loadnormalmap && skinframe->nmap == NULL)
3310 mymiplevel = savemiplevel;
3311 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3313 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 && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3317 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3319 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3320 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3321 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 && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3323 Mem_Free(bumppixels);
3325 else if (r_shadow_bumpscale_basetexture.value > 0)
3327 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3328 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3329 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 && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3332 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3333 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3336 // _luma is supported only for tenebrae compatibility
3337 // _glow is the preferred name
3338 mymiplevel = savemiplevel;
3339 if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow", skinframe->basename), false, false, false, &mymiplevel)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false, false, &mymiplevel))))
3341 skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_glow.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3342 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3343 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3344 Mem_Free(pixels);pixels = NULL;
3347 mymiplevel = savemiplevel;
3348 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3350 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_gloss.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3351 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3352 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3357 mymiplevel = savemiplevel;
3358 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3360 skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3361 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3362 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3367 mymiplevel = savemiplevel;
3368 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3370 skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3371 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3372 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3377 mymiplevel = savemiplevel;
3378 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3380 skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va("%s_reflect", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_reflectmask.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3381 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3382 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3388 Mem_Free(basepixels);
3393 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3394 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3397 unsigned char *temp1, *temp2;
3398 skinframe_t *skinframe;
3400 if (cls.state == ca_dedicated)
3403 // if already loaded just return it, otherwise make a new skinframe
3404 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3405 if (skinframe && skinframe->base)
3408 skinframe->stain = NULL;
3409 skinframe->merged = NULL;
3410 skinframe->base = NULL;
3411 skinframe->pants = NULL;
3412 skinframe->shirt = NULL;
3413 skinframe->nmap = NULL;
3414 skinframe->gloss = NULL;
3415 skinframe->glow = NULL;
3416 skinframe->fog = NULL;
3417 skinframe->reflect = NULL;
3418 skinframe->hasalpha = false;
3420 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3424 if (developer_loading.integer)
3425 Con_Printf("loading 32bit skin \"%s\"\n", name);
3427 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3429 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3430 temp2 = temp1 + width * height * 4;
3431 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3432 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);
3435 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3436 if (textureflags & TEXF_ALPHA)
3438 for (i = 3;i < width * height * 4;i += 4)
3440 if (skindata[i] < 255)
3442 skinframe->hasalpha = true;
3446 if (r_loadfog && skinframe->hasalpha)
3448 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3449 memcpy(fogpixels, skindata, width * height * 4);
3450 for (i = 0;i < width * height * 4;i += 4)
3451 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3452 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3453 Mem_Free(fogpixels);
3457 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3458 //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]);
3463 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3467 skinframe_t *skinframe;
3469 if (cls.state == ca_dedicated)
3472 // if already loaded just return it, otherwise make a new skinframe
3473 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3474 if (skinframe && skinframe->base)
3477 skinframe->stain = NULL;
3478 skinframe->merged = NULL;
3479 skinframe->base = NULL;
3480 skinframe->pants = NULL;
3481 skinframe->shirt = NULL;
3482 skinframe->nmap = NULL;
3483 skinframe->gloss = NULL;
3484 skinframe->glow = NULL;
3485 skinframe->fog = NULL;
3486 skinframe->reflect = NULL;
3487 skinframe->hasalpha = false;
3489 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3493 if (developer_loading.integer)
3494 Con_Printf("loading quake skin \"%s\"\n", name);
3496 // 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)
3497 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3498 memcpy(skinframe->qpixels, skindata, width*height);
3499 skinframe->qwidth = width;
3500 skinframe->qheight = height;
3503 for (i = 0;i < width * height;i++)
3504 featuresmask |= palette_featureflags[skindata[i]];
3506 skinframe->hasalpha = false;
3507 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3508 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3509 skinframe->qgeneratemerged = true;
3510 skinframe->qgeneratebase = skinframe->qhascolormapping;
3511 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3513 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3514 //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]);
3519 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3523 unsigned char *skindata;
3525 if (!skinframe->qpixels)
3528 if (!skinframe->qhascolormapping)
3529 colormapped = false;
3533 if (!skinframe->qgeneratebase)
3538 if (!skinframe->qgeneratemerged)
3542 width = skinframe->qwidth;
3543 height = skinframe->qheight;
3544 skindata = skinframe->qpixels;
3546 if (skinframe->qgeneratenmap)
3548 unsigned char *temp1, *temp2;
3549 skinframe->qgeneratenmap = false;
3550 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3551 temp2 = temp1 + width * height * 4;
3552 // use either a custom palette or the quake palette
3553 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3554 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3555 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);
3559 if (skinframe->qgenerateglow)
3561 skinframe->qgenerateglow = false;
3562 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3567 skinframe->qgeneratebase = false;
3568 skinframe->base = R_LoadTexture2D(r_main_texturepool, va("%s_nospecial", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap);
3569 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3570 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3574 skinframe->qgeneratemerged = false;
3575 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
3578 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3580 Mem_Free(skinframe->qpixels);
3581 skinframe->qpixels = NULL;
3585 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)
3588 skinframe_t *skinframe;
3590 if (cls.state == ca_dedicated)
3593 // if already loaded just return it, otherwise make a new skinframe
3594 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3595 if (skinframe && skinframe->base)
3598 skinframe->stain = NULL;
3599 skinframe->merged = NULL;
3600 skinframe->base = NULL;
3601 skinframe->pants = NULL;
3602 skinframe->shirt = NULL;
3603 skinframe->nmap = NULL;
3604 skinframe->gloss = NULL;
3605 skinframe->glow = NULL;
3606 skinframe->fog = NULL;
3607 skinframe->reflect = NULL;
3608 skinframe->hasalpha = false;
3610 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3614 if (developer_loading.integer)
3615 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3617 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3618 if (textureflags & TEXF_ALPHA)
3620 for (i = 0;i < width * height;i++)
3622 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3624 skinframe->hasalpha = true;
3628 if (r_loadfog && skinframe->hasalpha)
3629 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3632 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3633 //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]);
3638 skinframe_t *R_SkinFrame_LoadMissing(void)
3640 skinframe_t *skinframe;
3642 if (cls.state == ca_dedicated)
3645 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3646 skinframe->stain = NULL;
3647 skinframe->merged = NULL;
3648 skinframe->base = NULL;
3649 skinframe->pants = NULL;
3650 skinframe->shirt = NULL;
3651 skinframe->nmap = NULL;
3652 skinframe->gloss = NULL;
3653 skinframe->glow = NULL;
3654 skinframe->fog = NULL;
3655 skinframe->reflect = NULL;
3656 skinframe->hasalpha = false;
3658 skinframe->avgcolor[0] = rand() / RAND_MAX;
3659 skinframe->avgcolor[1] = rand() / RAND_MAX;
3660 skinframe->avgcolor[2] = rand() / RAND_MAX;
3661 skinframe->avgcolor[3] = 1;
3666 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3667 typedef struct suffixinfo_s
3670 qboolean flipx, flipy, flipdiagonal;
3673 static suffixinfo_t suffix[3][6] =
3676 {"px", false, false, false},
3677 {"nx", false, false, false},
3678 {"py", false, false, false},
3679 {"ny", false, false, false},
3680 {"pz", false, false, false},
3681 {"nz", false, false, false}
3684 {"posx", false, false, false},
3685 {"negx", false, false, false},
3686 {"posy", false, false, false},
3687 {"negy", false, false, false},
3688 {"posz", false, false, false},
3689 {"negz", false, false, false}
3692 {"rt", true, false, true},
3693 {"lf", false, true, true},
3694 {"ft", true, true, false},
3695 {"bk", false, false, false},
3696 {"up", true, false, true},
3697 {"dn", true, false, true}
3701 static int componentorder[4] = {0, 1, 2, 3};
3703 rtexture_t *R_LoadCubemap(const char *basename)
3705 int i, j, cubemapsize;
3706 unsigned char *cubemappixels, *image_buffer;
3707 rtexture_t *cubemaptexture;
3709 // must start 0 so the first loadimagepixels has no requested width/height
3711 cubemappixels = NULL;
3712 cubemaptexture = NULL;
3713 // keep trying different suffix groups (posx, px, rt) until one loads
3714 for (j = 0;j < 3 && !cubemappixels;j++)
3716 // load the 6 images in the suffix group
3717 for (i = 0;i < 6;i++)
3719 // generate an image name based on the base and and suffix
3720 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3722 if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3724 // an image loaded, make sure width and height are equal
3725 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3727 // if this is the first image to load successfully, allocate the cubemap memory
3728 if (!cubemappixels && image_width >= 1)
3730 cubemapsize = image_width;
3731 // note this clears to black, so unavailable sides are black
3732 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3734 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3736 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);
3739 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3741 Mem_Free(image_buffer);
3745 // if a cubemap loaded, upload it
3748 if (developer_loading.integer)
3749 Con_Printf("loading cubemap \"%s\"\n", basename);
3751 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer && gl_texturecompression.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
3752 Mem_Free(cubemappixels);
3756 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3757 if (developer_loading.integer)
3759 Con_Printf("(tried tried images ");
3760 for (j = 0;j < 3;j++)
3761 for (i = 0;i < 6;i++)
3762 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3763 Con_Print(" and was unable to find any of them).\n");
3766 return cubemaptexture;
3769 rtexture_t *R_GetCubemap(const char *basename)
3772 for (i = 0;i < r_texture_numcubemaps;i++)
3773 if (r_texture_cubemaps[i] != NULL)
3774 if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3775 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3776 if (i >= MAX_CUBEMAPS || !r_main_mempool)
3777 return r_texture_whitecube;
3778 r_texture_numcubemaps++;
3779 r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3780 strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3781 r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3782 return r_texture_cubemaps[i]->texture;
3785 void R_FreeCubemap(const char *basename)
3789 for (i = 0;i < r_texture_numcubemaps;i++)
3791 if (r_texture_cubemaps[i] != NULL)
3793 if (r_texture_cubemaps[i]->texture)
3795 if (developer_loading.integer)
3796 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3797 R_FreeTexture(r_texture_cubemaps[i]->texture);
3798 Mem_Free(r_texture_cubemaps[i]);
3799 r_texture_cubemaps[i] = NULL;
3805 void R_FreeCubemaps(void)
3808 for (i = 0;i < r_texture_numcubemaps;i++)
3810 if (developer_loading.integer)
3811 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3812 if (r_texture_cubemaps[i] != NULL)
3814 if (r_texture_cubemaps[i]->texture)
3815 R_FreeTexture(r_texture_cubemaps[i]->texture);
3816 Mem_Free(r_texture_cubemaps[i]);
3819 r_texture_numcubemaps = 0;
3822 void R_Main_FreeViewCache(void)
3824 if (r_refdef.viewcache.entityvisible)
3825 Mem_Free(r_refdef.viewcache.entityvisible);
3826 if (r_refdef.viewcache.world_pvsbits)
3827 Mem_Free(r_refdef.viewcache.world_pvsbits);
3828 if (r_refdef.viewcache.world_leafvisible)
3829 Mem_Free(r_refdef.viewcache.world_leafvisible);
3830 if (r_refdef.viewcache.world_surfacevisible)
3831 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3832 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3835 void R_Main_ResizeViewCache(void)
3837 int numentities = r_refdef.scene.numentities;
3838 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3839 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3840 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3841 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3842 if (r_refdef.viewcache.maxentities < numentities)
3844 r_refdef.viewcache.maxentities = numentities;
3845 if (r_refdef.viewcache.entityvisible)
3846 Mem_Free(r_refdef.viewcache.entityvisible);
3847 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3849 if (r_refdef.viewcache.world_numclusters != numclusters)
3851 r_refdef.viewcache.world_numclusters = numclusters;
3852 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3853 if (r_refdef.viewcache.world_pvsbits)
3854 Mem_Free(r_refdef.viewcache.world_pvsbits);
3855 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3857 if (r_refdef.viewcache.world_numleafs != numleafs)
3859 r_refdef.viewcache.world_numleafs = numleafs;
3860 if (r_refdef.viewcache.world_leafvisible)
3861 Mem_Free(r_refdef.viewcache.world_leafvisible);
3862 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3864 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3866 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3867 if (r_refdef.viewcache.world_surfacevisible)
3868 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3869 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3873 extern rtexture_t *loadingscreentexture;
3874 void gl_main_start(void)
3876 loadingscreentexture = NULL;
3877 r_texture_blanknormalmap = NULL;
3878 r_texture_white = NULL;
3879 r_texture_grey128 = NULL;
3880 r_texture_black = NULL;
3881 r_texture_whitecube = NULL;
3882 r_texture_normalizationcube = NULL;
3883 r_texture_fogattenuation = NULL;
3884 r_texture_fogheighttexture = NULL;
3885 r_texture_gammaramps = NULL;
3886 r_texture_numcubemaps = 0;
3888 r_loaddds = r_texture_dds_load.integer != 0;
3889 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3891 switch(vid.renderpath)
3893 case RENDERPATH_GL20:
3894 case RENDERPATH_D3D9:
3895 case RENDERPATH_D3D10:
3896 case RENDERPATH_D3D11:
3897 case RENDERPATH_SOFT:
3898 case RENDERPATH_GLES2:
3899 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3900 Cvar_SetValueQuick(&gl_combine, 1);
3901 Cvar_SetValueQuick(&r_glsl, 1);
3902 r_loadnormalmap = true;
3906 case RENDERPATH_GL13:
3907 case RENDERPATH_GLES1:
3908 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3909 Cvar_SetValueQuick(&gl_combine, 1);
3910 Cvar_SetValueQuick(&r_glsl, 0);
3911 r_loadnormalmap = false;
3912 r_loadgloss = false;
3915 case RENDERPATH_GL11:
3916 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3917 Cvar_SetValueQuick(&gl_combine, 0);
3918 Cvar_SetValueQuick(&r_glsl, 0);
3919 r_loadnormalmap = false;
3920 r_loadgloss = false;
3926 R_FrameData_Reset();
3930 memset(r_queries, 0, sizeof(r_queries));
3932 r_qwskincache = NULL;
3933 r_qwskincache_size = 0;
3935 // due to caching of texture_t references, the collision cache must be reset
3936 Collision_Cache_Reset(true);
3938 // set up r_skinframe loading system for textures
3939 memset(&r_skinframe, 0, sizeof(r_skinframe));
3940 r_skinframe.loadsequence = 1;
3941 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3943 r_main_texturepool = R_AllocTexturePool();
3944 R_BuildBlankTextures();
3946 if (vid.support.arb_texture_cube_map)
3949 R_BuildNormalizationCube();
3951 r_texture_fogattenuation = NULL;
3952 r_texture_fogheighttexture = NULL;
3953 r_texture_gammaramps = NULL;
3954 //r_texture_fogintensity = NULL;
3955 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3956 memset(&r_waterstate, 0, sizeof(r_waterstate));
3957 r_glsl_permutation = NULL;
3958 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3959 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3960 glslshaderstring = NULL;
3962 r_hlsl_permutation = NULL;
3963 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3964 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
3966 hlslshaderstring = NULL;
3967 memset(&r_svbsp, 0, sizeof (r_svbsp));
3969 memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
3970 r_texture_numcubemaps = 0;
3972 r_refdef.fogmasktable_density = 0;
3975 void gl_main_shutdown(void)
3978 R_FrameData_Reset();
3980 R_Main_FreeViewCache();
3982 switch(vid.renderpath)
3984 case RENDERPATH_GL11:
3985 case RENDERPATH_GL13:
3986 case RENDERPATH_GL20:
3987 case RENDERPATH_GLES1:
3988 case RENDERPATH_GLES2:
3990 qglDeleteQueriesARB(r_maxqueries, r_queries);
3992 case RENDERPATH_D3D9:
3993 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3995 case RENDERPATH_D3D10:
3996 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3998 case RENDERPATH_D3D11:
3999 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4001 case RENDERPATH_SOFT:
4007 memset(r_queries, 0, sizeof(r_queries));
4009 r_qwskincache = NULL;
4010 r_qwskincache_size = 0;
4012 // clear out the r_skinframe state
4013 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4014 memset(&r_skinframe, 0, sizeof(r_skinframe));
4017 Mem_Free(r_svbsp.nodes);
4018 memset(&r_svbsp, 0, sizeof (r_svbsp));
4019 R_FreeTexturePool(&r_main_texturepool);
4020 loadingscreentexture = NULL;
4021 r_texture_blanknormalmap = NULL;
4022 r_texture_white = NULL;
4023 r_texture_grey128 = NULL;
4024 r_texture_black = NULL;
4025 r_texture_whitecube = NULL;
4026 r_texture_normalizationcube = NULL;
4027 r_texture_fogattenuation = NULL;
4028 r_texture_fogheighttexture = NULL;
4029 r_texture_gammaramps = NULL;
4030 r_texture_numcubemaps = 0;
4031 //r_texture_fogintensity = NULL;
4032 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4033 memset(&r_waterstate, 0, sizeof(r_waterstate));
4036 r_glsl_permutation = NULL;
4037 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4038 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4039 glslshaderstring = NULL;
4041 r_hlsl_permutation = NULL;
4042 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4043 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4045 hlslshaderstring = NULL;
4048 extern void CL_ParseEntityLump(char *entitystring);
4049 void gl_main_newmap(void)
4051 // FIXME: move this code to client
4052 char *entities, entname[MAX_QPATH];
4054 Mem_Free(r_qwskincache);
4055 r_qwskincache = NULL;
4056 r_qwskincache_size = 0;
4059 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4060 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4062 CL_ParseEntityLump(entities);
4066 if (cl.worldmodel->brush.entities)
4067 CL_ParseEntityLump(cl.worldmodel->brush.entities);
4069 R_Main_FreeViewCache();
4071 R_FrameData_Reset();
4074 void GL_Main_Init(void)
4076 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4078 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4079 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4080 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4081 if (gamemode == GAME_NEHAHRA)
4083 Cvar_RegisterVariable (&gl_fogenable);
4084 Cvar_RegisterVariable (&gl_fogdensity);
4085 Cvar_RegisterVariable (&gl_fogred);
4086 Cvar_RegisterVariable (&gl_foggreen);
4087 Cvar_RegisterVariable (&gl_fogblue);
4088 Cvar_RegisterVariable (&gl_fogstart);
4089 Cvar_RegisterVariable (&gl_fogend);
4090 Cvar_RegisterVariable (&gl_skyclip);
4092 Cvar_RegisterVariable(&r_motionblur);
4093 Cvar_RegisterVariable(&r_motionblur_maxblur);
4094 Cvar_RegisterVariable(&r_motionblur_bmin);
4095 Cvar_RegisterVariable(&r_motionblur_vmin);
4096 Cvar_RegisterVariable(&r_motionblur_vmax);
4097 Cvar_RegisterVariable(&r_motionblur_vcoeff);
4098 Cvar_RegisterVariable(&r_motionblur_randomize);
4099 Cvar_RegisterVariable(&r_damageblur);
4100 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4101 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4102 Cvar_RegisterVariable(&r_equalize_entities_by);
4103 Cvar_RegisterVariable(&r_equalize_entities_to);
4104 Cvar_RegisterVariable(&r_depthfirst);
4105 Cvar_RegisterVariable(&r_useinfinitefarclip);
4106 Cvar_RegisterVariable(&r_farclip_base);
4107 Cvar_RegisterVariable(&r_farclip_world);
4108 Cvar_RegisterVariable(&r_nearclip);
4109 Cvar_RegisterVariable(&r_deformvertexes);
4110 Cvar_RegisterVariable(&r_transparent);
4111 Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4112 Cvar_RegisterVariable(&r_showoverdraw);
4113 Cvar_RegisterVariable(&r_showbboxes);
4114 Cvar_RegisterVariable(&r_showsurfaces);
4115 Cvar_RegisterVariable(&r_showtris);
4116 Cvar_RegisterVariable(&r_shownormals);
4117 Cvar_RegisterVariable(&r_showlighting);
4118 Cvar_RegisterVariable(&r_showshadowvolumes);
4119 Cvar_RegisterVariable(&r_showcollisionbrushes);
4120 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4121 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4122 Cvar_RegisterVariable(&r_showdisabledepthtest);
4123 Cvar_RegisterVariable(&r_drawportals);
4124 Cvar_RegisterVariable(&r_drawentities);
4125 Cvar_RegisterVariable(&r_draw2d);
4126 Cvar_RegisterVariable(&r_drawworld);
4127 Cvar_RegisterVariable(&r_cullentities_trace);
4128 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4129 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4130 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4131 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4132 Cvar_RegisterVariable(&r_drawviewmodel);
4133 Cvar_RegisterVariable(&r_drawexteriormodel);
4134 Cvar_RegisterVariable(&r_speeds);
4135 Cvar_RegisterVariable(&r_fullbrights);
4136 Cvar_RegisterVariable(&r_wateralpha);
4137 Cvar_RegisterVariable(&r_dynamic);
4138 Cvar_RegisterVariable(&r_fakelight);
4139 Cvar_RegisterVariable(&r_fakelight_intensity);
4140 Cvar_RegisterVariable(&r_fullbright);
4141 Cvar_RegisterVariable(&r_shadows);
4142 Cvar_RegisterVariable(&r_shadows_darken);
4143 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4144 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4145 Cvar_RegisterVariable(&r_shadows_throwdistance);
4146 Cvar_RegisterVariable(&r_shadows_throwdirection);
4147 Cvar_RegisterVariable(&r_shadows_focus);
4148 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4149 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4150 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4151 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4152 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4153 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4154 Cvar_RegisterVariable(&r_fog_exp2);
4155 Cvar_RegisterVariable(&r_fog_clear);
4156 Cvar_RegisterVariable(&r_drawfog);
4157 Cvar_RegisterVariable(&r_transparentdepthmasking);
4158 Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4159 Cvar_RegisterVariable(&r_transparent_sortarraysize);
4160 Cvar_RegisterVariable(&r_texture_dds_load);
4161 Cvar_RegisterVariable(&r_texture_dds_save);
4162 Cvar_RegisterVariable(&r_textureunits);
4163 Cvar_RegisterVariable(&gl_combine);
4164 Cvar_RegisterVariable(&r_viewfbo);
4165 Cvar_RegisterVariable(&r_viewscale);
4166 Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4167 Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4168 Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4169 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4170 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4171 Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4172 Cvar_RegisterVariable(&r_glsl);
4173 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4174 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4175 Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4176 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4177 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4178 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4179 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4180 Cvar_RegisterVariable(&r_glsl_postprocess);
4181 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4182 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4183 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4184 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4185 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4186 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4187 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4188 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4190 Cvar_RegisterVariable(&r_water);
4191 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4192 Cvar_RegisterVariable(&r_water_clippingplanebias);
4193 Cvar_RegisterVariable(&r_water_refractdistort);
4194 Cvar_RegisterVariable(&r_water_reflectdistort);
4195 Cvar_RegisterVariable(&r_water_scissormode);
4196 Cvar_RegisterVariable(&r_water_lowquality);
4198 Cvar_RegisterVariable(&r_lerpsprites);
4199 Cvar_RegisterVariable(&r_lerpmodels);
4200 Cvar_RegisterVariable(&r_lerplightstyles);
4201 Cvar_RegisterVariable(&r_waterscroll);
4202 Cvar_RegisterVariable(&r_bloom);
4203 Cvar_RegisterVariable(&r_bloom_colorscale);
4204 Cvar_RegisterVariable(&r_bloom_brighten);
4205 Cvar_RegisterVariable(&r_bloom_blur);
4206 Cvar_RegisterVariable(&r_bloom_resolution);
4207 Cvar_RegisterVariable(&r_bloom_colorexponent);
4208 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4209 Cvar_RegisterVariable(&r_hdr);
4210 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4211 Cvar_RegisterVariable(&r_hdr_glowintensity);
4212 Cvar_RegisterVariable(&r_hdr_range);
4213 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4214 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4215 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4216 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4217 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4218 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4219 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4220 Cvar_RegisterVariable(&developer_texturelogging);
4221 Cvar_RegisterVariable(&gl_lightmaps);
4222 Cvar_RegisterVariable(&r_test);
4223 Cvar_RegisterVariable(&r_glsl_saturation);
4224 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4225 Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4226 Cvar_RegisterVariable(&r_framedatasize);
4227 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4228 Cvar_SetValue("r_fullbrights", 0);
4229 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4232 extern void R_Textures_Init(void);
4233 extern void GL_Draw_Init(void);
4234 extern void GL_Main_Init(void);
4235 extern void R_Shadow_Init(void);
4236 extern void R_Sky_Init(void);
4237 extern void GL_Surf_Init(void);
4238 extern void R_Particles_Init(void);
4239 extern void R_Explosion_Init(void);
4240 extern void gl_backend_init(void);
4241 extern void Sbar_Init(void);
4242 extern void R_LightningBeams_Init(void);
4243 extern void Mod_RenderInit(void);
4244 extern void Font_Init(void);
4246 void Render_Init(void)
4259 R_LightningBeams_Init();
4268 extern char *ENGINE_EXTENSIONS;
4271 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4272 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4273 gl_version = (const char *)qglGetString(GL_VERSION);
4274 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4278 if (!gl_platformextensions)
4279 gl_platformextensions = "";
4281 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4282 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4283 Con_Printf("GL_VERSION: %s\n", gl_version);
4284 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4285 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4287 VID_CheckExtensions();
4289 // LordHavoc: report supported extensions
4290 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4292 // clear to black (loading plaque will be seen over this)
4293 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4296 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4300 if (r_trippy.integer)
4302 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4304 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4307 p = r_refdef.view.frustum + i;
4312 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4316 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4320 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4324 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4328 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4332 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4336 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4340 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4348 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4352 if (r_trippy.integer)
4354 for (i = 0;i < numplanes;i++)
4361 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4365 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4369 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4373 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4377 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4381 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4385 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4389 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4397 //==================================================================================
4399 // LordHavoc: this stores temporary data used within the same frame
4401 typedef struct r_framedata_mem_s
4403 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4404 size_t size; // how much usable space
4405 size_t current; // how much space in use
4406 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4407 size_t wantedsize; // how much space was allocated
4408 unsigned char *data; // start of real data (16byte aligned)
4412 static r_framedata_mem_t *r_framedata_mem;
4414 void R_FrameData_Reset(void)
4416 while (r_framedata_mem)
4418 r_framedata_mem_t *next = r_framedata_mem->purge;
4419 Mem_Free(r_framedata_mem);
4420 r_framedata_mem = next;
4424 void R_FrameData_Resize(void)
4427 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4428 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4429 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4431 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4432 newmem->wantedsize = wantedsize;
4433 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4434 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4435 newmem->current = 0;
4437 newmem->purge = r_framedata_mem;
4438 r_framedata_mem = newmem;
4442 void R_FrameData_NewFrame(void)
4444 R_FrameData_Resize();
4445 if (!r_framedata_mem)
4447 // if we ran out of space on the last frame, free the old memory now
4448 while (r_framedata_mem->purge)
4450 // repeatedly remove the second item in the list, leaving only head
4451 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4452 Mem_Free(r_framedata_mem->purge);
4453 r_framedata_mem->purge = next;
4455 // reset the current mem pointer
4456 r_framedata_mem->current = 0;
4457 r_framedata_mem->mark = 0;
4460 void *R_FrameData_Alloc(size_t size)
4464 // align to 16 byte boundary - the data pointer is already aligned, so we
4465 // only need to ensure the size of every allocation is also aligned
4466 size = (size + 15) & ~15;
4468 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4470 // emergency - we ran out of space, allocate more memory
4471 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4472 R_FrameData_Resize();
4475 data = r_framedata_mem->data + r_framedata_mem->current;
4476 r_framedata_mem->current += size;
4478 // count the usage for stats
4479 r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4480 r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4482 return (void *)data;
4485 void *R_FrameData_Store(size_t size, void *data)
4487 void *d = R_FrameData_Alloc(size);
4489 memcpy(d, data, size);
4493 void R_FrameData_SetMark(void)
4495 if (!r_framedata_mem)
4497 r_framedata_mem->mark = r_framedata_mem->current;
4500 void R_FrameData_ReturnToMark(void)
4502 if (!r_framedata_mem)
4504 r_framedata_mem->current = r_framedata_mem->mark;
4507 //==================================================================================
4509 // LordHavoc: animcache originally written by Echon, rewritten since then
4512 * Animation cache prevents re-generating mesh data for an animated model
4513 * multiple times in one frame for lighting, shadowing, reflections, etc.
4516 void R_AnimCache_Free(void)
4520 void R_AnimCache_ClearCache(void)
4523 entity_render_t *ent;
4525 for (i = 0;i < r_refdef.scene.numentities;i++)
4527 ent = r_refdef.scene.entities[i];
4528 ent->animcache_vertex3f = NULL;
4529 ent->animcache_normal3f = NULL;
4530 ent->animcache_svector3f = NULL;
4531 ent->animcache_tvector3f = NULL;
4532 ent->animcache_vertexmesh = NULL;
4533 ent->animcache_vertex3fbuffer = NULL;
4534 ent->animcache_vertexmeshbuffer = NULL;
4538 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4542 // check if we need the meshbuffers
4543 if (!vid.useinterleavedarrays)
4546 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4547 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4548 // TODO: upload vertex3f buffer?
4549 if (ent->animcache_vertexmesh)
4551 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4552 for (i = 0;i < numvertices;i++)
4553 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4554 if (ent->animcache_svector3f)
4555 for (i = 0;i < numvertices;i++)
4556 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4557 if (ent->animcache_tvector3f)
4558 for (i = 0;i < numvertices;i++)
4559 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4560 if (ent->animcache_normal3f)
4561 for (i = 0;i < numvertices;i++)
4562 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4563 // TODO: upload vertexmeshbuffer?
4567 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4569 dp_model_t *model = ent->model;
4571 // see if it's already cached this frame
4572 if (ent->animcache_vertex3f)
4574 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4575 if (wantnormals || wanttangents)
4577 if (ent->animcache_normal3f)
4578 wantnormals = false;
4579 if (ent->animcache_svector3f)
4580 wanttangents = false;
4581 if (wantnormals || wanttangents)
4583 numvertices = model->surfmesh.num_vertices;
4585 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4588 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4589 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4591 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4592 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4598 // see if this ent is worth caching
4599 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4601 // get some memory for this entity and generate mesh data
4602 numvertices = model->surfmesh.num_vertices;
4603 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4605 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4608 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4609 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4611 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4612 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4617 void R_AnimCache_CacheVisibleEntities(void)
4620 qboolean wantnormals = true;
4621 qboolean wanttangents = !r_showsurfaces.integer;
4623 switch(vid.renderpath)
4625 case RENDERPATH_GL20:
4626 case RENDERPATH_D3D9:
4627 case RENDERPATH_D3D10:
4628 case RENDERPATH_D3D11:
4629 case RENDERPATH_GLES2:
4631 case RENDERPATH_GL11:
4632 case RENDERPATH_GL13:
4633 case RENDERPATH_GLES1:
4634 wanttangents = false;
4636 case RENDERPATH_SOFT:
4640 if (r_shownormals.integer)
4641 wanttangents = wantnormals = true;
4643 // TODO: thread this
4644 // NOTE: R_PrepareRTLights() also caches entities
4646 for (i = 0;i < r_refdef.scene.numentities;i++)
4647 if (r_refdef.viewcache.entityvisible[i])
4648 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4651 //==================================================================================
4653 extern cvar_t r_overheadsprites_pushback;
4655 static void R_View_UpdateEntityLighting (void)
4658 entity_render_t *ent;
4659 vec3_t tempdiffusenormal, avg;
4660 vec_t f, fa, fd, fdd;
4661 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4663 for (i = 0;i < r_refdef.scene.numentities;i++)
4665 ent = r_refdef.scene.entities[i];
4667 // skip unseen models
4668 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4672 if (ent->model && ent->model->brush.num_leafs)
4674 // TODO: use modellight for r_ambient settings on world?
4675 VectorSet(ent->modellight_ambient, 0, 0, 0);
4676 VectorSet(ent->modellight_diffuse, 0, 0, 0);
4677 VectorSet(ent->modellight_lightdir, 0, 0, 1);
4681 // fetch the lighting from the worldmodel data
4682 VectorClear(ent->modellight_ambient);
4683 VectorClear(ent->modellight_diffuse);
4684 VectorClear(tempdiffusenormal);
4685 if (ent->flags & RENDER_LIGHT)
4688 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4690 // complete lightning for lit sprites
4691 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4692 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4694 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4695 org[2] = org[2] + r_overheadsprites_pushback.value;
4696 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4699 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4701 if(ent->flags & RENDER_EQUALIZE)
4703 // first fix up ambient lighting...
4704 if(r_equalize_entities_minambient.value > 0)
4706 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4709 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4710 if(fa < r_equalize_entities_minambient.value * fd)
4713 // fa'/fd' = minambient
4714 // fa'+0.25*fd' = fa+0.25*fd
4716 // fa' = fd' * minambient
4717 // fd'*(0.25+minambient) = fa+0.25*fd
4719 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4720 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4722 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4723 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
4724 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4725 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4730 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4732 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4733 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4737 // adjust brightness and saturation to target
4738 avg[0] = avg[1] = avg[2] = fa / f;
4739 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4740 avg[0] = avg[1] = avg[2] = fd / f;
4741 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4747 VectorSet(ent->modellight_ambient, 1, 1, 1);
4749 // move the light direction into modelspace coordinates for lighting code
4750 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4751 if(VectorLength2(ent->modellight_lightdir) == 0)
4752 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4753 VectorNormalize(ent->modellight_lightdir);
4757 #define MAX_LINEOFSIGHTTRACES 64
4759 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4762 vec3_t boxmins, boxmaxs;
4765 dp_model_t *model = r_refdef.scene.worldmodel;
4767 if (!model || !model->brush.TraceLineOfSight)
4770 // expand the box a little
4771 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4772 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4773 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4774 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4775 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4776 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4778 // return true if eye is inside enlarged box
4779 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4783 VectorCopy(eye, start);
4784 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4785 if (model->brush.TraceLineOfSight(model, start, end))
4788 // try various random positions
4789 for (i = 0;i < numsamples;i++)
4791 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4792 if (model->brush.TraceLineOfSight(model, start, end))
4800 static void R_View_UpdateEntityVisible (void)
4805 entity_render_t *ent;
4807 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4808 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4809 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
4810 : RENDER_EXTERIORMODEL;
4811 if (!r_drawviewmodel.integer)
4812 renderimask |= RENDER_VIEWMODEL;
4813 if (!r_drawexteriormodel.integer)
4814 renderimask |= RENDER_EXTERIORMODEL;
4815 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4817 // worldmodel can check visibility
4818 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4819 for (i = 0;i < r_refdef.scene.numentities;i++)
4821 ent = r_refdef.scene.entities[i];
4822 if (!(ent->flags & renderimask))
4823 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)))
4824 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))
4825 r_refdef.viewcache.entityvisible[i] = true;
4830 // no worldmodel or it can't check visibility
4831 for (i = 0;i < r_refdef.scene.numentities;i++)
4833 ent = r_refdef.scene.entities[i];
4834 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));
4837 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
4838 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4840 for (i = 0;i < r_refdef.scene.numentities;i++)
4842 if (!r_refdef.viewcache.entityvisible[i])
4844 ent = r_refdef.scene.entities[i];
4845 if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4847 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4849 continue; // temp entities do pvs only
4850 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4851 ent->last_trace_visibility = realtime;
4852 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4853 r_refdef.viewcache.entityvisible[i] = 0;
4859 /// only used if skyrendermasked, and normally returns false
4860 int R_DrawBrushModelsSky (void)
4863 entity_render_t *ent;
4866 for (i = 0;i < r_refdef.scene.numentities;i++)
4868 if (!r_refdef.viewcache.entityvisible[i])
4870 ent = r_refdef.scene.entities[i];
4871 if (!ent->model || !ent->model->DrawSky)
4873 ent->model->DrawSky(ent);
4879 static void R_DrawNoModel(entity_render_t *ent);
4880 static void R_DrawModels(void)
4883 entity_render_t *ent;
4885 for (i = 0;i < r_refdef.scene.numentities;i++)
4887 if (!r_refdef.viewcache.entityvisible[i])
4889 ent = r_refdef.scene.entities[i];
4890 r_refdef.stats.entities++;
4892 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
4895 Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
4896 Con_Printf("R_DrawModels\n");
4897 Con_Printf("model %s O %f %f %f F %f %f %f L %f %f %f U %f %f %f\n", ent->model->name, o[0], o[1], o[2], f[0], f[1], f[2], l[0], l[1], l[2], u[0], u[1], u[2]);
4898 Con_Printf("group: %i %f %i %f %i %f %i %f\n", ent->framegroupblend[0].frame, ent->framegroupblend[0].lerp, ent->framegroupblend[1].frame, ent->framegroupblend[1].lerp, ent->framegroupblend[2].frame, ent->framegroupblend[2].lerp, ent->framegroupblend[3].frame, ent->framegroupblend[3].lerp);
4899 Con_Printf("blend: %i %f %i %f %i %f %i %f %i %f %i %f %i %f %i %f\n", ent->frameblend[0].subframe, ent->frameblend[0].lerp, ent->frameblend[1].subframe, ent->frameblend[1].lerp, ent->frameblend[2].subframe, ent->frameblend[2].lerp, ent->frameblend[3].subframe, ent->frameblend[3].lerp, ent->frameblend[4].subframe, ent->frameblend[4].lerp, ent->frameblend[5].subframe, ent->frameblend[5].lerp, ent->frameblend[6].subframe, ent->frameblend[6].lerp, ent->frameblend[7].subframe, ent->frameblend[7].lerp);
4902 if (ent->model && ent->model->Draw != NULL)
4903 ent->model->Draw(ent);
4909 static void R_DrawModelsDepth(void)
4912 entity_render_t *ent;
4914 for (i = 0;i < r_refdef.scene.numentities;i++)
4916 if (!r_refdef.viewcache.entityvisible[i])
4918 ent = r_refdef.scene.entities[i];
4919 if (ent->model && ent->model->DrawDepth != NULL)
4920 ent->model->DrawDepth(ent);
4924 static void R_DrawModelsDebug(void)
4927 entity_render_t *ent;
4929 for (i = 0;i < r_refdef.scene.numentities;i++)
4931 if (!r_refdef.viewcache.entityvisible[i])
4933 ent = r_refdef.scene.entities[i];
4934 if (ent->model && ent->model->DrawDebug != NULL)
4935 ent->model->DrawDebug(ent);
4939 static void R_DrawModelsAddWaterPlanes(void)
4942 entity_render_t *ent;
4944 for (i = 0;i < r_refdef.scene.numentities;i++)
4946 if (!r_refdef.viewcache.entityvisible[i])
4948 ent = r_refdef.scene.entities[i];
4949 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4950 ent->model->DrawAddWaterPlanes(ent);
4954 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4956 if (r_hdr_irisadaptation.integer)
4960 vec3_t diffusenormal;
4965 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4966 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
4967 brightness = max(0.0000001f, brightness);
4968 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4969 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4970 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
4971 current = r_hdr_irisadaptation_value.value;
4973 current = min(current + adjust, goal);
4974 else if (current > goal)
4975 current = max(current - adjust, goal);
4976 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4977 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4979 else if (r_hdr_irisadaptation_value.value != 1.0f)
4980 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4983 static void R_View_SetFrustum(const int *scissor)
4986 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
4987 vec3_t forward, left, up, origin, v;
4991 // flipped x coordinates (because x points left here)
4992 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4993 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4995 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
4996 switch(vid.renderpath)
4998 case RENDERPATH_D3D9:
4999 case RENDERPATH_D3D10:
5000 case RENDERPATH_D3D11:
5001 // non-flipped y coordinates
5002 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5003 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5005 case RENDERPATH_SOFT:
5006 case RENDERPATH_GL11:
5007 case RENDERPATH_GL13:
5008 case RENDERPATH_GL20:
5009 case RENDERPATH_GLES1:
5010 case RENDERPATH_GLES2:
5011 // non-flipped y coordinates
5012 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5013 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5018 // we can't trust r_refdef.view.forward and friends in reflected scenes
5019 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5022 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5023 r_refdef.view.frustum[0].normal[1] = 0 - 0;
5024 r_refdef.view.frustum[0].normal[2] = -1 - 0;
5025 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5026 r_refdef.view.frustum[1].normal[1] = 0 + 0;
5027 r_refdef.view.frustum[1].normal[2] = -1 + 0;
5028 r_refdef.view.frustum[2].normal[0] = 0 - 0;
5029 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5030 r_refdef.view.frustum[2].normal[2] = -1 - 0;
5031 r_refdef.view.frustum[3].normal[0] = 0 + 0;
5032 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5033 r_refdef.view.frustum[3].normal[2] = -1 + 0;
5037 zNear = r_refdef.nearclip;
5038 nudge = 1.0 - 1.0 / (1<<23);
5039 r_refdef.view.frustum[4].normal[0] = 0 - 0;
5040 r_refdef.view.frustum[4].normal[1] = 0 - 0;
5041 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5042 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5043 r_refdef.view.frustum[5].normal[0] = 0 + 0;
5044 r_refdef.view.frustum[5].normal[1] = 0 + 0;
5045 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5046 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5052 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5053 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5054 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5055 r_refdef.view.frustum[0].dist = m[15] - m[12];
5057 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5058 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5059 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5060 r_refdef.view.frustum[1].dist = m[15] + m[12];
5062 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5063 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5064 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5065 r_refdef.view.frustum[2].dist = m[15] - m[13];
5067 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5068 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5069 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5070 r_refdef.view.frustum[3].dist = m[15] + m[13];
5072 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5073 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5074 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5075 r_refdef.view.frustum[4].dist = m[15] - m[14];
5077 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5078 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5079 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5080 r_refdef.view.frustum[5].dist = m[15] + m[14];
5083 if (r_refdef.view.useperspective)
5085 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5086 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]);
5087 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]);
5088 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]);
5089 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]);
5091 // then the normals from the corners relative to origin
5092 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5093 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5094 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5095 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5097 // in a NORMAL view, forward cross left == up
5098 // in a REFLECTED view, forward cross left == down
5099 // so our cross products above need to be adjusted for a left handed coordinate system
5100 CrossProduct(forward, left, v);
5101 if(DotProduct(v, up) < 0)
5103 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5104 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5105 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5106 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5109 // Leaving those out was a mistake, those were in the old code, and they
5110 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5111 // I couldn't reproduce it after adding those normalizations. --blub
5112 VectorNormalize(r_refdef.view.frustum[0].normal);
5113 VectorNormalize(r_refdef.view.frustum[1].normal);
5114 VectorNormalize(r_refdef.view.frustum[2].normal);
5115 VectorNormalize(r_refdef.view.frustum[3].normal);
5117 // make the corners absolute
5118 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5119 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5120 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5121 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5124 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5126 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5127 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5128 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5129 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5130 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5134 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5135 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5136 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5137 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5138 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5139 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5140 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5141 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5142 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5143 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5145 r_refdef.view.numfrustumplanes = 5;
5147 if (r_refdef.view.useclipplane)
5149 r_refdef.view.numfrustumplanes = 6;
5150 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5153 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5154 PlaneClassify(r_refdef.view.frustum + i);
5156 // LordHavoc: note to all quake engine coders, Quake had a special case
5157 // for 90 degrees which assumed a square view (wrong), so I removed it,
5158 // Quake2 has it disabled as well.
5160 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5161 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5162 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5163 //PlaneClassify(&frustum[0]);
5165 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5166 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5167 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5168 //PlaneClassify(&frustum[1]);
5170 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5171 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5172 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5173 //PlaneClassify(&frustum[2]);
5175 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5176 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5177 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5178 //PlaneClassify(&frustum[3]);
5181 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5182 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5183 //PlaneClassify(&frustum[4]);
5186 void R_View_UpdateWithScissor(const int *myscissor)
5188 R_Main_ResizeViewCache();
5189 R_View_SetFrustum(myscissor);
5190 R_View_WorldVisibility(r_refdef.view.useclipplane);
5191 R_View_UpdateEntityVisible();
5192 R_View_UpdateEntityLighting();
5195 void R_View_Update(void)
5197 R_Main_ResizeViewCache();
5198 R_View_SetFrustum(NULL);
5199 R_View_WorldVisibility(r_refdef.view.useclipplane);
5200 R_View_UpdateEntityVisible();
5201 R_View_UpdateEntityLighting();
5204 float viewscalefpsadjusted = 1.0f;
5206 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5208 float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5209 scale = bound(0.03125f, scale, 1.0f);
5210 *outwidth = (int)ceil(width * scale);
5211 *outheight = (int)ceil(height * scale);
5214 void R_Mesh_SetMainRenderTargets(void)
5216 if (r_bloomstate.fbo_framebuffer)
5217 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5219 R_Mesh_ResetRenderTargets();
5222 void R_SetupView(qboolean allowwaterclippingplane)
5224 const float *customclipplane = NULL;
5226 int scaledwidth, scaledheight;
5227 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5229 // LordHavoc: couldn't figure out how to make this approach the
5230 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5231 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5232 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5233 dist = r_refdef.view.clipplane.dist;
5234 plane[0] = r_refdef.view.clipplane.normal[0];
5235 plane[1] = r_refdef.view.clipplane.normal[1];
5236 plane[2] = r_refdef.view.clipplane.normal[2];
5238 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5241 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5242 if (!r_refdef.view.useperspective)
5243 R_Viewport_InitOrtho(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, -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);
5244 else if (vid.stencil && r_useinfinitefarclip.integer)
5245 R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane);
5247 R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip, customclipplane);
5248 R_Mesh_SetMainRenderTargets();
5249 R_SetViewport(&r_refdef.view.viewport);
5250 if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5252 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5253 float screenplane[4];
5254 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5255 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5256 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5257 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5258 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5262 void R_EntityMatrix(const matrix4x4_t *matrix)
5264 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5266 gl_modelmatrixchanged = false;
5267 gl_modelmatrix = *matrix;
5268 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5269 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5270 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5271 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5273 switch(vid.renderpath)
5275 case RENDERPATH_D3D9:
5277 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5278 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5281 case RENDERPATH_D3D10:
5282 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5284 case RENDERPATH_D3D11:
5285 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5287 case RENDERPATH_GL11:
5288 case RENDERPATH_GL13:
5289 case RENDERPATH_GLES1:
5290 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5292 case RENDERPATH_SOFT:
5293 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5294 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5296 case RENDERPATH_GL20:
5297 case RENDERPATH_GLES2:
5298 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5299 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5305 void R_ResetViewRendering2D(void)
5307 r_viewport_t viewport;
5310 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5311 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);
5312 R_Mesh_ResetRenderTargets();
5313 R_SetViewport(&viewport);
5314 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5315 GL_Color(1, 1, 1, 1);
5316 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5317 GL_BlendFunc(GL_ONE, GL_ZERO);
5318 GL_ScissorTest(false);
5319 GL_DepthMask(false);
5320 GL_DepthRange(0, 1);
5321 GL_DepthTest(false);
5322 GL_DepthFunc(GL_LEQUAL);
5323 R_EntityMatrix(&identitymatrix);
5324 R_Mesh_ResetTextureState();
5325 GL_PolygonOffset(0, 0);
5326 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5327 switch(vid.renderpath)
5329 case RENDERPATH_GL11:
5330 case RENDERPATH_GL13:
5331 case RENDERPATH_GL20:
5332 case RENDERPATH_GLES1:
5333 case RENDERPATH_GLES2:
5334 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5336 case RENDERPATH_D3D9:
5337 case RENDERPATH_D3D10:
5338 case RENDERPATH_D3D11:
5339 case RENDERPATH_SOFT:
5342 GL_CullFace(GL_NONE);
5345 void R_ResetViewRendering3D(void)
5350 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5351 GL_Color(1, 1, 1, 1);
5352 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5353 GL_BlendFunc(GL_ONE, GL_ZERO);
5354 GL_ScissorTest(true);
5356 GL_DepthRange(0, 1);
5358 GL_DepthFunc(GL_LEQUAL);
5359 R_EntityMatrix(&identitymatrix);
5360 R_Mesh_ResetTextureState();
5361 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5362 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5363 switch(vid.renderpath)
5365 case RENDERPATH_GL11:
5366 case RENDERPATH_GL13:
5367 case RENDERPATH_GL20:
5368 case RENDERPATH_GLES1:
5369 case RENDERPATH_GLES2:
5370 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5372 case RENDERPATH_D3D9:
5373 case RENDERPATH_D3D10:
5374 case RENDERPATH_D3D11:
5375 case RENDERPATH_SOFT:
5378 GL_CullFace(r_refdef.view.cullface_back);
5383 R_RenderView_UpdateViewVectors
5386 static void R_RenderView_UpdateViewVectors(void)
5388 // break apart the view matrix into vectors for various purposes
5389 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5390 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5391 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5392 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5393 // make an inverted copy of the view matrix for tracking sprites
5394 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5397 void R_RenderScene(void);
5398 void R_RenderWaterPlanes(void);
5400 static void R_Water_StartFrame(void)
5403 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5404 r_waterstate_waterplane_t *p;
5406 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5409 switch(vid.renderpath)
5411 case RENDERPATH_GL20:
5412 case RENDERPATH_D3D9:
5413 case RENDERPATH_D3D10:
5414 case RENDERPATH_D3D11:
5415 case RENDERPATH_SOFT:
5416 case RENDERPATH_GLES2:
5418 case RENDERPATH_GL11:
5419 case RENDERPATH_GL13:
5420 case RENDERPATH_GLES1:
5424 // set waterwidth and waterheight to the water resolution that will be
5425 // used (often less than the screen resolution for faster rendering)
5426 R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5428 // calculate desired texture sizes
5429 // can't use water if the card does not support the texture size
5430 if (!r_water.integer || r_showsurfaces.integer)
5431 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5432 else if (vid.support.arb_texture_non_power_of_two)
5434 texturewidth = waterwidth;
5435 textureheight = waterheight;
5436 camerawidth = waterwidth;
5437 cameraheight = waterheight;
5441 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5442 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5443 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
5444 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
5447 // allocate textures as needed
5448 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5450 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5451 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5453 if (p->texture_refraction)
5454 R_FreeTexture(p->texture_refraction);
5455 p->texture_refraction = NULL;
5456 if (p->texture_reflection)
5457 R_FreeTexture(p->texture_reflection);
5458 p->texture_reflection = NULL;
5459 if (p->texture_camera)
5460 R_FreeTexture(p->texture_camera);
5461 p->texture_camera = NULL;
5463 memset(&r_waterstate, 0, sizeof(r_waterstate));
5464 r_waterstate.texturewidth = texturewidth;
5465 r_waterstate.textureheight = textureheight;
5466 r_waterstate.camerawidth = camerawidth;
5467 r_waterstate.cameraheight = cameraheight;
5470 if (r_waterstate.texturewidth)
5472 int scaledwidth, scaledheight;
5474 r_waterstate.enabled = true;
5476 // when doing a reduced render (HDR) we want to use a smaller area
5477 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5478 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5479 R_GetScaledViewSize(r_waterstate.waterwidth, r_waterstate.waterheight, &scaledwidth, &scaledheight);
5481 // set up variables that will be used in shader setup
5482 r_waterstate.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5483 r_waterstate.screenscale[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5484 r_waterstate.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5485 r_waterstate.screencenter[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5488 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5489 r_waterstate.numwaterplanes = 0;
5492 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5494 int triangleindex, planeindex;
5500 r_waterstate_waterplane_t *p;
5501 texture_t *t = R_GetCurrentTexture(surface->texture);
5503 // just use the first triangle with a valid normal for any decisions
5504 VectorClear(normal);
5505 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5507 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5508 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5509 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5510 TriangleNormal(vert[0], vert[1], vert[2], normal);
5511 if (VectorLength2(normal) >= 0.001)
5515 VectorCopy(normal, plane.normal);
5516 VectorNormalize(plane.normal);
5517 plane.dist = DotProduct(vert[0], plane.normal);
5518 PlaneClassify(&plane);
5519 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5521 // skip backfaces (except if nocullface is set)
5522 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5524 VectorNegate(plane.normal, plane.normal);
5526 PlaneClassify(&plane);
5530 // find a matching plane if there is one
5531 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5532 if(p->camera_entity == t->camera_entity)
5533 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5535 if (planeindex >= r_waterstate.maxwaterplanes)
5536 return; // nothing we can do, out of planes
5538 // if this triangle does not fit any known plane rendered this frame, add one
5539 if (planeindex >= r_waterstate.numwaterplanes)
5541 // store the new plane
5542 r_waterstate.numwaterplanes++;
5544 // clear materialflags and pvs
5545 p->materialflags = 0;
5546 p->pvsvalid = false;
5547 p->camera_entity = t->camera_entity;
5548 VectorCopy(surface->mins, p->mins);
5549 VectorCopy(surface->maxs, p->maxs);
5554 p->mins[0] = min(p->mins[0], surface->mins[0]);
5555 p->mins[1] = min(p->mins[1], surface->mins[1]);
5556 p->mins[2] = min(p->mins[2], surface->mins[2]);
5557 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5558 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5559 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5561 // merge this surface's materialflags into the waterplane
5562 p->materialflags |= t->currentmaterialflags;
5563 if(!(p->materialflags & MATERIALFLAG_CAMERA))
5565 // merge this surface's PVS into the waterplane
5566 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5567 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5568 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5570 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5576 extern cvar_t r_drawparticles;
5577 extern cvar_t r_drawdecals;
5579 static void R_Water_ProcessPlanes(void)
5582 r_refdef_view_t originalview;
5583 r_refdef_view_t myview;
5584 int planeindex, qualityreduction = 0, old_r_dynamic = 0, old_r_shadows = 0, old_r_worldrtlight = 0, old_r_dlight = 0, old_r_particles = 0, old_r_decals = 0;
5585 r_waterstate_waterplane_t *p;
5588 originalview = r_refdef.view;
5590 // lowquality hack, temporarily shut down some cvars and restore afterwards
5591 qualityreduction = r_water_lowquality.integer;
5592 if (qualityreduction > 0)
5594 if (qualityreduction >= 1)
5596 old_r_shadows = r_shadows.integer;
5597 old_r_worldrtlight = r_shadow_realtime_world.integer;
5598 old_r_dlight = r_shadow_realtime_dlight.integer;
5599 Cvar_SetValueQuick(&r_shadows, 0);
5600 Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5601 Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5603 if (qualityreduction >= 2)
5605 old_r_dynamic = r_dynamic.integer;
5606 old_r_particles = r_drawparticles.integer;
5607 old_r_decals = r_drawdecals.integer;
5608 Cvar_SetValueQuick(&r_dynamic, 0);
5609 Cvar_SetValueQuick(&r_drawparticles, 0);
5610 Cvar_SetValueQuick(&r_drawdecals, 0);
5614 // make sure enough textures are allocated
5615 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5617 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5619 if (!p->texture_refraction)
5620 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);
5621 if (!p->texture_refraction)
5624 else if (p->materialflags & MATERIALFLAG_CAMERA)
5626 if (!p->texture_camera)
5627 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);
5628 if (!p->texture_camera)
5632 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5634 if (!p->texture_reflection)
5635 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);
5636 if (!p->texture_reflection)
5642 r_refdef.view = originalview;
5643 r_refdef.view.showdebug = false;
5644 r_refdef.view.width = r_waterstate.waterwidth;
5645 r_refdef.view.height = r_waterstate.waterheight;
5646 r_refdef.view.useclipplane = true;
5647 myview = r_refdef.view;
5648 r_waterstate.renderingscene = true;
5649 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5651 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5653 r_refdef.view = myview;
5654 if(r_water_scissormode.integer)
5657 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5658 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5661 // render reflected scene and copy into texture
5662 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5663 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5664 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5665 r_refdef.view.clipplane = p->plane;
5666 // reverse the cullface settings for this render
5667 r_refdef.view.cullface_front = GL_FRONT;
5668 r_refdef.view.cullface_back = GL_BACK;
5669 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5671 r_refdef.view.usecustompvs = true;
5673 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5675 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5678 R_ResetViewRendering3D();
5679 R_ClearScreen(r_refdef.fogenabled);
5680 if(r_water_scissormode.integer & 2)
5681 R_View_UpdateWithScissor(myscissor);
5684 if(r_water_scissormode.integer & 1)
5685 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5688 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);
5691 // render the normal view scene and copy into texture
5692 // (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)
5693 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5695 r_refdef.view = myview;
5696 if(r_water_scissormode.integer)
5699 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5700 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5703 r_waterstate.renderingrefraction = true;
5705 r_refdef.view.clipplane = p->plane;
5706 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5707 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5709 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5711 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5712 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5713 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5714 R_RenderView_UpdateViewVectors();
5715 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5717 r_refdef.view.usecustompvs = true;
5718 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);
5722 PlaneClassify(&r_refdef.view.clipplane);
5724 R_ResetViewRendering3D();
5725 R_ClearScreen(r_refdef.fogenabled);
5726 if(r_water_scissormode.integer & 2)
5727 R_View_UpdateWithScissor(myscissor);
5730 if(r_water_scissormode.integer & 1)
5731 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5734 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);
5735 r_waterstate.renderingrefraction = false;
5737 else if (p->materialflags & MATERIALFLAG_CAMERA)
5739 r_refdef.view = myview;
5741 r_refdef.view.clipplane = p->plane;
5742 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5743 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5745 r_refdef.view.width = r_waterstate.camerawidth;
5746 r_refdef.view.height = r_waterstate.cameraheight;
5747 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5748 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5750 if(p->camera_entity)
5752 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5753 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5756 // note: all of the view is used for displaying... so
5757 // there is no use in scissoring
5759 // reverse the cullface settings for this render
5760 r_refdef.view.cullface_front = GL_FRONT;
5761 r_refdef.view.cullface_back = GL_BACK;
5762 // also reverse the view matrix
5763 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
5764 R_RenderView_UpdateViewVectors();
5765 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5767 r_refdef.view.usecustompvs = true;
5768 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);
5771 // camera needs no clipplane
5772 r_refdef.view.useclipplane = false;
5774 PlaneClassify(&r_refdef.view.clipplane);
5776 R_ResetViewRendering3D();
5777 R_ClearScreen(r_refdef.fogenabled);
5781 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);
5782 r_waterstate.renderingrefraction = false;
5786 if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5787 r_waterstate.renderingscene = false;
5788 r_refdef.view = originalview;
5789 R_ResetViewRendering3D();
5790 R_ClearScreen(r_refdef.fogenabled);
5794 r_refdef.view = originalview;
5795 r_waterstate.renderingscene = false;
5796 Cvar_SetValueQuick(&r_water, 0);
5797 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
5799 // lowquality hack, restore cvars
5800 if (qualityreduction > 0)
5802 if (qualityreduction >= 1)
5804 Cvar_SetValueQuick(&r_shadows, old_r_shadows);
5805 Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
5806 Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
5808 if (qualityreduction >= 2)
5810 Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
5811 Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
5812 Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
5817 void R_Bloom_StartFrame(void)
5819 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5820 int viewwidth, viewheight;
5823 if (r_viewscale_fpsscaling.integer)
5825 double actualframetime;
5826 double targetframetime;
5828 actualframetime = r_refdef.lastdrawscreentime;
5829 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5830 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5831 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5832 if (r_viewscale_fpsscaling_stepsize.value > 0)
5833 adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5834 viewscalefpsadjusted += adjust;
5835 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5838 viewscalefpsadjusted = 1.0f;
5840 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5842 switch(vid.renderpath)
5844 case RENDERPATH_GL20:
5845 case RENDERPATH_D3D9:
5846 case RENDERPATH_D3D10:
5847 case RENDERPATH_D3D11:
5848 case RENDERPATH_SOFT:
5849 case RENDERPATH_GLES2:
5851 case RENDERPATH_GL11:
5852 case RENDERPATH_GL13:
5853 case RENDERPATH_GLES1:
5857 // set bloomwidth and bloomheight to the bloom resolution that will be
5858 // used (often less than the screen resolution for faster rendering)
5859 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5860 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5861 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5862 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5863 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5865 // calculate desired texture sizes
5866 if (vid.support.arb_texture_non_power_of_two)
5868 screentexturewidth = vid.width;
5869 screentextureheight = vid.height;
5870 bloomtexturewidth = r_bloomstate.bloomwidth;
5871 bloomtextureheight = r_bloomstate.bloomheight;
5875 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
5876 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
5877 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
5878 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
5881 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))
5883 Cvar_SetValueQuick(&r_hdr, 0);
5884 Cvar_SetValueQuick(&r_bloom, 0);
5885 Cvar_SetValueQuick(&r_motionblur, 0);
5886 Cvar_SetValueQuick(&r_damageblur, 0);
5889 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)) && r_viewfbo.integer < 1 && r_viewscale.value == 1.0f && !r_viewscale_fpsscaling.integer)
5890 screentexturewidth = screentextureheight = 0;
5891 if (!r_hdr.integer && !r_bloom.integer)
5892 bloomtexturewidth = bloomtextureheight = 0;
5894 textype = TEXTYPE_COLORBUFFER;
5895 switch (vid.renderpath)
5897 case RENDERPATH_GL20:
5898 case RENDERPATH_GLES2:
5899 if (vid.support.ext_framebuffer_object)
5901 if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5902 if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5905 case RENDERPATH_GL11:
5906 case RENDERPATH_GL13:
5907 case RENDERPATH_GLES1:
5908 case RENDERPATH_D3D9:
5909 case RENDERPATH_D3D10:
5910 case RENDERPATH_D3D11:
5911 case RENDERPATH_SOFT:
5915 // allocate textures as needed
5916 if (r_bloomstate.screentexturewidth != screentexturewidth
5917 || r_bloomstate.screentextureheight != screentextureheight
5918 || r_bloomstate.bloomtexturewidth != bloomtexturewidth
5919 || r_bloomstate.bloomtextureheight != bloomtextureheight
5920 || r_bloomstate.texturetype != textype
5921 || r_bloomstate.viewfbo != r_viewfbo.integer)
5923 if (r_bloomstate.texture_bloom)
5924 R_FreeTexture(r_bloomstate.texture_bloom);
5925 r_bloomstate.texture_bloom = NULL;
5926 if (r_bloomstate.texture_screen)
5927 R_FreeTexture(r_bloomstate.texture_screen);
5928 r_bloomstate.texture_screen = NULL;
5929 if (r_bloomstate.fbo_framebuffer)
5930 R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
5931 r_bloomstate.fbo_framebuffer = 0;
5932 if (r_bloomstate.texture_framebuffercolor)
5933 R_FreeTexture(r_bloomstate.texture_framebuffercolor);
5934 r_bloomstate.texture_framebuffercolor = NULL;
5935 if (r_bloomstate.texture_framebufferdepth)
5936 R_FreeTexture(r_bloomstate.texture_framebufferdepth);
5937 r_bloomstate.texture_framebufferdepth = NULL;
5938 r_bloomstate.screentexturewidth = screentexturewidth;
5939 r_bloomstate.screentextureheight = screentextureheight;
5940 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5941 r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5942 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
5944 // FIXME: choose depth bits based on a cvar
5945 r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
5946 r_bloomstate.texture_framebuffercolor = R_LoadTexture2D(r_main_texturepool, "framebuffercolor", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5947 r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5948 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5949 // render depth into one texture and normalmap into the other
5953 qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5954 qglReadBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5955 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
5956 if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
5957 Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
5960 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5961 r_bloomstate.bloomtextureheight = bloomtextureheight;
5962 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5963 r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5964 r_bloomstate.viewfbo = r_viewfbo.integer;
5965 r_bloomstate.texturetype = textype;
5968 // when doing a reduced render (HDR) we want to use a smaller area
5969 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5970 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5971 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5972 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5973 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5975 // set up a texcoord array for the full resolution screen image
5976 // (we have to keep this around to copy back during final render)
5977 r_bloomstate.screentexcoord2f[0] = 0;
5978 r_bloomstate.screentexcoord2f[1] = (float)viewheight / (float)r_bloomstate.screentextureheight;
5979 r_bloomstate.screentexcoord2f[2] = (float)viewwidth / (float)r_bloomstate.screentexturewidth;
5980 r_bloomstate.screentexcoord2f[3] = (float)viewheight / (float)r_bloomstate.screentextureheight;
5981 r_bloomstate.screentexcoord2f[4] = (float)viewwidth / (float)r_bloomstate.screentexturewidth;
5982 r_bloomstate.screentexcoord2f[5] = 0;
5983 r_bloomstate.screentexcoord2f[6] = 0;
5984 r_bloomstate.screentexcoord2f[7] = 0;
5986 // set up a texcoord array for the reduced resolution bloom image
5987 // (which will be additive blended over the screen image)
5988 r_bloomstate.bloomtexcoord2f[0] = 0;
5989 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5990 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5991 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5992 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5993 r_bloomstate.bloomtexcoord2f[5] = 0;
5994 r_bloomstate.bloomtexcoord2f[6] = 0;
5995 r_bloomstate.bloomtexcoord2f[7] = 0;
5997 switch(vid.renderpath)
5999 case RENDERPATH_GL11:
6000 case RENDERPATH_GL13:
6001 case RENDERPATH_GL20:
6002 case RENDERPATH_SOFT:
6003 case RENDERPATH_GLES1:
6004 case RENDERPATH_GLES2:
6006 case RENDERPATH_D3D9:
6007 case RENDERPATH_D3D10:
6008 case RENDERPATH_D3D11:
6011 for (i = 0;i < 4;i++)
6013 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
6014 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
6015 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
6016 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
6022 if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth)
6024 r_bloomstate.enabled = true;
6025 r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer;
6028 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);
6030 if (r_bloomstate.fbo_framebuffer)
6031 r_refdef.view.clear = true;
6034 void R_Bloom_CopyBloomTexture(float colorscale)
6036 r_refdef.stats.bloom++;
6038 // scale down screen texture to the bloom texture size
6040 R_Mesh_SetMainRenderTargets();
6041 R_SetViewport(&r_bloomstate.viewport);
6042 GL_BlendFunc(GL_ONE, GL_ZERO);
6043 GL_Color(colorscale, colorscale, colorscale, 1);
6044 // 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...
6045 switch(vid.renderpath)
6047 case RENDERPATH_GL11:
6048 case RENDERPATH_GL13:
6049 case RENDERPATH_GL20:
6050 case RENDERPATH_GLES1:
6051 case RENDERPATH_GLES2:
6052 case RENDERPATH_SOFT:
6053 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6055 case RENDERPATH_D3D9:
6056 case RENDERPATH_D3D10:
6057 case RENDERPATH_D3D11:
6058 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6061 // TODO: do boxfilter scale-down in shader?
6062 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, true);
6063 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6064 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6066 // we now have a bloom image in the framebuffer
6067 // copy it into the bloom image texture for later processing
6068 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);
6069 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6072 void R_Bloom_CopyHDRTexture(void)
6074 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);
6075 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6078 void R_Bloom_MakeTexture(void)
6081 float xoffset, yoffset, r, brighten;
6083 r_refdef.stats.bloom++;
6085 R_ResetViewRendering2D();
6087 // we have a bloom image in the framebuffer
6089 R_SetViewport(&r_bloomstate.viewport);
6091 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6094 r = bound(0, r_bloom_colorexponent.value / x, 1);
6095 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6097 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
6098 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, true);
6099 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6100 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6102 // copy the vertically blurred bloom view to a texture
6103 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);
6104 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6107 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
6108 brighten = r_bloom_brighten.value;
6109 if (r_bloomstate.hdr)
6110 brighten *= r_hdr_range.value;
6111 brighten = sqrt(brighten);
6113 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6114 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, true);
6116 for (dir = 0;dir < 2;dir++)
6118 // blend on at multiple vertical offsets to achieve a vertical blur
6119 // TODO: do offset blends using GLSL
6120 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6121 GL_BlendFunc(GL_ONE, GL_ZERO);
6122 for (x = -range;x <= range;x++)
6124 if (!dir){xoffset = 0;yoffset = x;}
6125 else {xoffset = x;yoffset = 0;}
6126 xoffset /= (float)r_bloomstate.bloomtexturewidth;
6127 yoffset /= (float)r_bloomstate.bloomtextureheight;
6128 // compute a texcoord array with the specified x and y offset
6129 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
6130 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6131 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6132 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6133 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6134 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
6135 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
6136 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
6137 // this r value looks like a 'dot' particle, fading sharply to
6138 // black at the edges
6139 // (probably not realistic but looks good enough)
6140 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6141 //r = brighten/(range*2+1);
6142 r = brighten / (range * 2 + 1);
6144 r *= (1 - x*x/(float)(range*range));
6145 GL_Color(r, r, r, 1);
6146 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6147 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6148 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6149 GL_BlendFunc(GL_ONE, GL_ONE);
6152 // copy the vertically blurred bloom view to a texture
6153 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);
6154 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6158 void R_HDR_RenderBloomTexture(void)
6160 int oldwidth, oldheight;
6161 float oldcolorscale;
6162 qboolean oldwaterstate;
6164 oldwaterstate = r_waterstate.enabled;
6165 oldcolorscale = r_refdef.view.colorscale;
6166 oldwidth = r_refdef.view.width;
6167 oldheight = r_refdef.view.height;
6168 r_refdef.view.width = r_bloomstate.bloomwidth;
6169 r_refdef.view.height = r_bloomstate.bloomheight;
6171 if(r_hdr.integer < 2)
6172 r_waterstate.enabled = false;
6174 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
6175 // TODO: add exposure compensation features
6176 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6178 r_refdef.view.showdebug = false;
6179 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6181 R_ResetViewRendering3D();
6183 R_ClearScreen(r_refdef.fogenabled);
6184 if (r_timereport_active)
6185 R_TimeReport("HDRclear");
6188 if (r_timereport_active)
6189 R_TimeReport("visibility");
6191 // only do secondary renders with HDR if r_hdr is 2 or higher
6192 r_waterstate.numwaterplanes = 0;
6193 if (r_waterstate.enabled)
6194 R_RenderWaterPlanes();
6196 r_refdef.view.showdebug = true;
6198 r_waterstate.numwaterplanes = 0;
6200 R_ResetViewRendering2D();
6202 R_Bloom_CopyHDRTexture();
6203 R_Bloom_MakeTexture();
6205 // restore the view settings
6206 r_waterstate.enabled = oldwaterstate;
6207 r_refdef.view.width = oldwidth;
6208 r_refdef.view.height = oldheight;
6209 r_refdef.view.colorscale = oldcolorscale;
6211 R_ResetViewRendering3D();
6213 R_ClearScreen(r_refdef.fogenabled);
6214 if (r_timereport_active)
6215 R_TimeReport("viewclear");
6218 static void R_BlendView(void)
6220 unsigned int permutation;
6221 float uservecs[4][4];
6223 switch (vid.renderpath)
6225 case RENDERPATH_GL20:
6226 case RENDERPATH_D3D9:
6227 case RENDERPATH_D3D10:
6228 case RENDERPATH_D3D11:
6229 case RENDERPATH_SOFT:
6230 case RENDERPATH_GLES2:
6232 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6233 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6234 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6235 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6236 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6238 if (r_bloomstate.texture_screen)
6240 // make sure the buffer is available
6241 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6243 R_ResetViewRendering2D();
6244 R_Mesh_SetMainRenderTargets();
6246 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6248 // declare variables
6250 static float avgspeed;
6252 speed = VectorLength(cl.movement_velocity);
6254 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
6255 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
6257 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
6258 speed = bound(0, speed, 1);
6259 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
6261 // calculate values into a standard alpha
6262 cl.motionbluralpha = 1 - exp(-
6264 (r_motionblur.value * speed / 80)
6266 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6269 max(0.0001, cl.time - cl.oldtime) // fps independent
6272 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6273 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6275 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6277 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6278 GL_Color(1, 1, 1, cl.motionbluralpha);
6279 switch(vid.renderpath)
6281 case RENDERPATH_GL11:
6282 case RENDERPATH_GL13:
6283 case RENDERPATH_GL20:
6284 case RENDERPATH_GLES1:
6285 case RENDERPATH_GLES2:
6286 case RENDERPATH_SOFT:
6287 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6289 case RENDERPATH_D3D9:
6290 case RENDERPATH_D3D10:
6291 case RENDERPATH_D3D11:
6292 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6295 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, true);
6296 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6297 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6301 // copy view into the screen texture
6302 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);
6303 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6305 else if (!r_bloomstate.texture_bloom)
6307 // we may still have to do view tint...
6308 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6310 // apply a color tint to the whole view
6311 R_ResetViewRendering2D();
6312 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6313 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6314 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, true);
6315 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6316 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6318 break; // no screen processing, no bloom, skip it
6321 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6323 // render simple bloom effect
6324 // copy the screen and shrink it and darken it for the bloom process
6325 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6326 // make the bloom texture
6327 R_Bloom_MakeTexture();
6330 #if _MSC_VER >= 1400
6331 #define sscanf sscanf_s
6333 memset(uservecs, 0, sizeof(uservecs));
6334 if (r_glsl_postprocess_uservec1_enable.integer)
6335 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6336 if (r_glsl_postprocess_uservec2_enable.integer)
6337 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6338 if (r_glsl_postprocess_uservec3_enable.integer)
6339 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6340 if (r_glsl_postprocess_uservec4_enable.integer)
6341 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6343 R_ResetViewRendering2D();
6344 GL_Color(1, 1, 1, 1);
6345 GL_BlendFunc(GL_ONE, GL_ZERO);
6347 switch(vid.renderpath)
6349 case RENDERPATH_GL20:
6350 case RENDERPATH_GLES2:
6351 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6352 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6353 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_bloomstate.texture_screen);
6354 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_bloomstate.texture_bloom );
6355 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6356 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]);
6357 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6358 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]);
6359 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]);
6360 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]);
6361 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]);
6362 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6363 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6364 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);
6366 case RENDERPATH_D3D9:
6368 // 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...
6369 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6370 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6371 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6372 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6373 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6374 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6375 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6376 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6377 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6378 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6379 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6380 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6381 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6382 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6385 case RENDERPATH_D3D10:
6386 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6388 case RENDERPATH_D3D11:
6389 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6391 case RENDERPATH_SOFT:
6392 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6393 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6394 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6395 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6396 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6397 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6398 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6399 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6400 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6401 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6402 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6403 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6404 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6405 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6410 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6411 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6413 case RENDERPATH_GL11:
6414 case RENDERPATH_GL13:
6415 case RENDERPATH_GLES1:
6416 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6418 // apply a color tint to the whole view
6419 R_ResetViewRendering2D();
6420 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6421 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6422 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, true);
6423 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6424 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6430 matrix4x4_t r_waterscrollmatrix;
6432 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6434 if (r_refdef.fog_density)
6436 r_refdef.fogcolor[0] = r_refdef.fog_red;
6437 r_refdef.fogcolor[1] = r_refdef.fog_green;
6438 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6440 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6441 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6442 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6443 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6447 VectorCopy(r_refdef.fogcolor, fogvec);
6448 // color.rgb *= ContrastBoost * SceneBrightness;
6449 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6450 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6451 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6452 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6457 void R_UpdateVariables(void)
6461 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6463 r_refdef.farclip = r_farclip_base.value;
6464 if (r_refdef.scene.worldmodel)
6465 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6466 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6468 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6469 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6470 r_refdef.polygonfactor = 0;
6471 r_refdef.polygonoffset = 0;
6472 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6473 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6475 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6476 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6477 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6478 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6479 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6480 if (FAKELIGHT_ENABLED)
6482 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6484 if (r_showsurfaces.integer)
6486 r_refdef.scene.rtworld = false;
6487 r_refdef.scene.rtworldshadows = false;
6488 r_refdef.scene.rtdlight = false;
6489 r_refdef.scene.rtdlightshadows = false;
6490 r_refdef.lightmapintensity = 0;
6493 if (gamemode == GAME_NEHAHRA)
6495 if (gl_fogenable.integer)
6497 r_refdef.oldgl_fogenable = true;
6498 r_refdef.fog_density = gl_fogdensity.value;
6499 r_refdef.fog_red = gl_fogred.value;
6500 r_refdef.fog_green = gl_foggreen.value;
6501 r_refdef.fog_blue = gl_fogblue.value;
6502 r_refdef.fog_alpha = 1;
6503 r_refdef.fog_start = 0;
6504 r_refdef.fog_end = gl_skyclip.value;
6505 r_refdef.fog_height = 1<<30;
6506 r_refdef.fog_fadedepth = 128;
6508 else if (r_refdef.oldgl_fogenable)
6510 r_refdef.oldgl_fogenable = false;
6511 r_refdef.fog_density = 0;
6512 r_refdef.fog_red = 0;
6513 r_refdef.fog_green = 0;
6514 r_refdef.fog_blue = 0;
6515 r_refdef.fog_alpha = 0;
6516 r_refdef.fog_start = 0;
6517 r_refdef.fog_end = 0;
6518 r_refdef.fog_height = 1<<30;
6519 r_refdef.fog_fadedepth = 128;
6523 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6524 r_refdef.fog_start = max(0, r_refdef.fog_start);
6525 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6527 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6529 if (r_refdef.fog_density && r_drawfog.integer)
6531 r_refdef.fogenabled = true;
6532 // this is the point where the fog reaches 0.9986 alpha, which we
6533 // consider a good enough cutoff point for the texture
6534 // (0.9986 * 256 == 255.6)
6535 if (r_fog_exp2.integer)
6536 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6538 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6539 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6540 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6541 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6542 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6543 R_BuildFogHeightTexture();
6544 // fog color was already set
6545 // update the fog texture
6546 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)
6547 R_BuildFogTexture();
6548 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6549 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6552 r_refdef.fogenabled = false;
6554 switch(vid.renderpath)
6556 case RENDERPATH_GL20:
6557 case RENDERPATH_D3D9:
6558 case RENDERPATH_D3D10:
6559 case RENDERPATH_D3D11:
6560 case RENDERPATH_SOFT:
6561 case RENDERPATH_GLES2:
6562 if(v_glslgamma.integer && !vid_gammatables_trivial)
6564 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6566 // build GLSL gamma texture
6567 #define RAMPWIDTH 256
6568 unsigned short ramp[RAMPWIDTH * 3];
6569 unsigned char rampbgr[RAMPWIDTH][4];
6572 r_texture_gammaramps_serial = vid_gammatables_serial;
6574 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6575 for(i = 0; i < RAMPWIDTH; ++i)
6577 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6578 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6579 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6582 if (r_texture_gammaramps)
6584 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6588 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6594 // remove GLSL gamma texture
6597 case RENDERPATH_GL11:
6598 case RENDERPATH_GL13:
6599 case RENDERPATH_GLES1:
6604 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6605 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6611 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6612 if( scenetype != r_currentscenetype ) {
6613 // store the old scenetype
6614 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6615 r_currentscenetype = scenetype;
6616 // move in the new scene
6617 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6626 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6628 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6629 if( scenetype == r_currentscenetype ) {
6630 return &r_refdef.scene;
6632 return &r_scenes_store[ scenetype ];
6641 int dpsoftrast_test;
6642 void R_RenderView(void)
6644 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6646 dpsoftrast_test = r_test.integer;
6648 if (r_timereport_active)
6649 R_TimeReport("start");
6650 r_textureframe++; // used only by R_GetCurrentTexture
6651 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6653 if(R_CompileShader_CheckStaticParms())
6656 if (!r_drawentities.integer)
6657 r_refdef.scene.numentities = 0;
6659 R_AnimCache_ClearCache();
6660 R_FrameData_NewFrame();
6662 /* adjust for stereo display */
6663 if(R_Stereo_Active())
6665 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);
6666 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6669 if (r_refdef.view.isoverlay)
6671 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6672 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6673 R_TimeReport("depthclear");
6675 r_refdef.view.showdebug = false;
6677 r_waterstate.enabled = false;
6678 r_waterstate.numwaterplanes = 0;
6682 r_refdef.view.matrix = originalmatrix;
6688 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6690 r_refdef.view.matrix = originalmatrix;
6691 return; //Host_Error ("R_RenderView: NULL worldmodel");
6694 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6696 R_RenderView_UpdateViewVectors();
6698 R_Shadow_UpdateWorldLightSelection();
6700 R_Bloom_StartFrame();
6701 R_Water_StartFrame();
6704 if (r_timereport_active)
6705 R_TimeReport("viewsetup");
6707 R_ResetViewRendering3D();
6709 if (r_refdef.view.clear || r_refdef.fogenabled)
6711 R_ClearScreen(r_refdef.fogenabled);
6712 if (r_timereport_active)
6713 R_TimeReport("viewclear");
6715 r_refdef.view.clear = true;
6717 // this produces a bloom texture to be used in R_BlendView() later
6718 if (r_bloomstate.hdr)
6720 R_HDR_RenderBloomTexture();
6721 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6722 r_textureframe++; // used only by R_GetCurrentTexture
6725 r_refdef.view.showdebug = true;
6728 if (r_timereport_active)
6729 R_TimeReport("visibility");
6731 r_waterstate.numwaterplanes = 0;
6732 if (r_waterstate.enabled)
6733 R_RenderWaterPlanes();
6736 r_waterstate.numwaterplanes = 0;
6739 if (r_timereport_active)
6740 R_TimeReport("blendview");
6742 GL_Scissor(0, 0, vid.width, vid.height);
6743 GL_ScissorTest(false);
6745 r_refdef.view.matrix = originalmatrix;
6750 void R_RenderWaterPlanes(void)
6752 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6754 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6755 if (r_timereport_active)
6756 R_TimeReport("waterworld");
6759 // don't let sound skip if going slow
6760 if (r_refdef.scene.extraupdate)
6763 R_DrawModelsAddWaterPlanes();
6764 if (r_timereport_active)
6765 R_TimeReport("watermodels");
6767 if (r_waterstate.numwaterplanes)
6769 R_Water_ProcessPlanes();
6770 if (r_timereport_active)
6771 R_TimeReport("waterscenes");
6775 extern void R_DrawLightningBeams (void);
6776 extern void VM_CL_AddPolygonsToMeshQueue (void);
6777 extern void R_DrawPortals (void);
6778 extern cvar_t cl_locs_show;
6779 static void R_DrawLocs(void);
6780 static void R_DrawEntityBBoxes(void);
6781 static void R_DrawModelDecals(void);
6782 extern void R_DrawModelShadows(void);
6783 extern void R_DrawModelShadowMaps(void);
6784 extern cvar_t cl_decals_newsystem;
6785 extern qboolean r_shadow_usingdeferredprepass;
6786 void R_RenderScene(void)
6788 qboolean shadowmapping = false;
6790 if (r_timereport_active)
6791 R_TimeReport("beginscene");
6793 r_refdef.stats.renders++;
6797 // don't let sound skip if going slow
6798 if (r_refdef.scene.extraupdate)
6801 R_MeshQueue_BeginScene();
6805 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);
6807 if (r_timereport_active)
6808 R_TimeReport("skystartframe");
6810 if (cl.csqc_vidvars.drawworld)
6812 // don't let sound skip if going slow
6813 if (r_refdef.scene.extraupdate)
6816 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6818 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6819 if (r_timereport_active)
6820 R_TimeReport("worldsky");
6823 if (R_DrawBrushModelsSky() && r_timereport_active)
6824 R_TimeReport("bmodelsky");
6826 if (skyrendermasked && skyrenderlater)
6828 // we have to force off the water clipping plane while rendering sky
6832 if (r_timereport_active)
6833 R_TimeReport("sky");
6837 R_AnimCache_CacheVisibleEntities();
6838 if (r_timereport_active)
6839 R_TimeReport("animation");
6841 R_Shadow_PrepareLights();
6842 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6843 R_Shadow_PrepareModelShadows();
6844 if (r_timereport_active)
6845 R_TimeReport("preparelights");
6847 if (R_Shadow_ShadowMappingEnabled())
6848 shadowmapping = true;
6850 if (r_shadow_usingdeferredprepass)
6851 R_Shadow_DrawPrepass();
6853 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6855 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6856 if (r_timereport_active)
6857 R_TimeReport("worlddepth");
6859 if (r_depthfirst.integer >= 2)
6861 R_DrawModelsDepth();
6862 if (r_timereport_active)
6863 R_TimeReport("modeldepth");
6866 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6868 R_DrawModelShadowMaps();
6869 R_ResetViewRendering3D();
6870 // don't let sound skip if going slow
6871 if (r_refdef.scene.extraupdate)
6875 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6877 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6878 if (r_timereport_active)
6879 R_TimeReport("world");
6882 // don't let sound skip if going slow
6883 if (r_refdef.scene.extraupdate)
6887 if (r_timereport_active)
6888 R_TimeReport("models");
6890 // don't let sound skip if going slow
6891 if (r_refdef.scene.extraupdate)
6894 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6896 R_DrawModelShadows();
6897 R_ResetViewRendering3D();
6898 // don't let sound skip if going slow
6899 if (r_refdef.scene.extraupdate)
6903 if (!r_shadow_usingdeferredprepass)
6905 R_Shadow_DrawLights();
6906 if (r_timereport_active)
6907 R_TimeReport("rtlights");
6910 // don't let sound skip if going slow
6911 if (r_refdef.scene.extraupdate)
6914 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6916 R_DrawModelShadows();
6917 R_ResetViewRendering3D();
6918 // don't let sound skip if going slow
6919 if (r_refdef.scene.extraupdate)
6923 if (cl.csqc_vidvars.drawworld)
6925 if (cl_decals_newsystem.integer)
6927 R_DrawModelDecals();
6928 if (r_timereport_active)
6929 R_TimeReport("modeldecals");
6934 if (r_timereport_active)
6935 R_TimeReport("decals");
6939 if (r_timereport_active)
6940 R_TimeReport("particles");
6943 if (r_timereport_active)
6944 R_TimeReport("explosions");
6946 R_DrawLightningBeams();
6947 if (r_timereport_active)
6948 R_TimeReport("lightning");
6951 VM_CL_AddPolygonsToMeshQueue();
6953 if (r_refdef.view.showdebug)
6955 if (cl_locs_show.integer)
6958 if (r_timereport_active)
6959 R_TimeReport("showlocs");
6962 if (r_drawportals.integer)
6965 if (r_timereport_active)
6966 R_TimeReport("portals");
6969 if (r_showbboxes.value > 0)
6971 R_DrawEntityBBoxes();
6972 if (r_timereport_active)
6973 R_TimeReport("bboxes");
6977 if (r_transparent.integer)
6979 R_MeshQueue_RenderTransparent();
6980 if (r_timereport_active)
6981 R_TimeReport("drawtrans");
6984 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 || r_showoverdraw.value > 0))
6986 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6987 if (r_timereport_active)
6988 R_TimeReport("worlddebug");
6989 R_DrawModelsDebug();
6990 if (r_timereport_active)
6991 R_TimeReport("modeldebug");
6994 if (cl.csqc_vidvars.drawworld)
6996 R_Shadow_DrawCoronas();
6997 if (r_timereport_active)
6998 R_TimeReport("coronas");
7003 GL_DepthTest(false);
7004 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7005 GL_Color(1, 1, 1, 1);
7006 qglBegin(GL_POLYGON);
7007 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7008 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7009 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7010 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7012 qglBegin(GL_POLYGON);
7013 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]);
7014 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]);
7015 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]);
7016 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]);
7018 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7022 // don't let sound skip if going slow
7023 if (r_refdef.scene.extraupdate)
7026 R_ResetViewRendering2D();
7029 static const unsigned short bboxelements[36] =
7039 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7042 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7044 RSurf_ActiveWorldEntity();
7046 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7047 GL_DepthMask(false);
7048 GL_DepthRange(0, 1);
7049 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7050 // R_Mesh_ResetTextureState();
7052 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7053 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7054 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7055 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7056 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7057 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7058 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7059 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7060 R_FillColors(color4f, 8, cr, cg, cb, ca);
7061 if (r_refdef.fogenabled)
7063 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7065 f1 = RSurf_FogVertex(v);
7067 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7068 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7069 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7072 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7073 R_Mesh_ResetTextureState();
7074 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
7075 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7078 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7082 prvm_edict_t *edict;
7083 prvm_prog_t *prog_save = prog;
7085 // this function draws bounding boxes of server entities
7089 GL_CullFace(GL_NONE);
7090 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
7094 for (i = 0;i < numsurfaces;i++)
7096 edict = PRVM_EDICT_NUM(surfacelist[i]);
7097 switch ((int)edict->fields.server->solid)
7099 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
7100 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
7101 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
7102 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7103 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
7104 default: Vector4Set(color, 0, 0, 0, 0.50);break;
7106 color[3] *= r_showbboxes.value;
7107 color[3] = bound(0, color[3], 1);
7108 GL_DepthTest(!r_showdisabledepthtest.integer);
7109 GL_CullFace(r_refdef.view.cullface_front);
7110 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7116 static void R_DrawEntityBBoxes(void)
7119 prvm_edict_t *edict;
7121 prvm_prog_t *prog_save = prog;
7123 // this function draws bounding boxes of server entities
7129 for (i = 0;i < prog->num_edicts;i++)
7131 edict = PRVM_EDICT_NUM(i);
7132 if (edict->priv.server->free)
7134 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7135 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7137 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7139 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7140 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7146 static const int nomodelelement3i[24] =
7158 static const unsigned short nomodelelement3s[24] =
7170 static const float nomodelvertex3f[6*3] =
7180 static const float nomodelcolor4f[6*4] =
7182 0.0f, 0.0f, 0.5f, 1.0f,
7183 0.0f, 0.0f, 0.5f, 1.0f,
7184 0.0f, 0.5f, 0.0f, 1.0f,
7185 0.0f, 0.5f, 0.0f, 1.0f,
7186 0.5f, 0.0f, 0.0f, 1.0f,
7187 0.5f, 0.0f, 0.0f, 1.0f
7190 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7196 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);
7198 // this is only called once per entity so numsurfaces is always 1, and
7199 // surfacelist is always {0}, so this code does not handle batches
7201 if (rsurface.ent_flags & RENDER_ADDITIVE)
7203 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7204 GL_DepthMask(false);
7206 else if (rsurface.colormod[3] < 1)
7208 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7209 GL_DepthMask(false);
7213 GL_BlendFunc(GL_ONE, GL_ZERO);
7216 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7217 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7218 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7219 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7220 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7221 for (i = 0, c = color4f;i < 6;i++, c += 4)
7223 c[0] *= rsurface.colormod[0];
7224 c[1] *= rsurface.colormod[1];
7225 c[2] *= rsurface.colormod[2];
7226 c[3] *= rsurface.colormod[3];
7228 if (r_refdef.fogenabled)
7230 for (i = 0, c = color4f;i < 6;i++, c += 4)
7232 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7234 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7235 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7236 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7239 // R_Mesh_ResetTextureState();
7240 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
7241 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7242 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7245 void R_DrawNoModel(entity_render_t *ent)
7248 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7249 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7250 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7252 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7255 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7257 vec3_t right1, right2, diff, normal;
7259 VectorSubtract (org2, org1, normal);
7261 // calculate 'right' vector for start
7262 VectorSubtract (r_refdef.view.origin, org1, diff);
7263 CrossProduct (normal, diff, right1);
7264 VectorNormalize (right1);
7266 // calculate 'right' vector for end
7267 VectorSubtract (r_refdef.view.origin, org2, diff);
7268 CrossProduct (normal, diff, right2);
7269 VectorNormalize (right2);
7271 vert[ 0] = org1[0] + width * right1[0];
7272 vert[ 1] = org1[1] + width * right1[1];
7273 vert[ 2] = org1[2] + width * right1[2];
7274 vert[ 3] = org1[0] - width * right1[0];
7275 vert[ 4] = org1[1] - width * right1[1];
7276 vert[ 5] = org1[2] - width * right1[2];
7277 vert[ 6] = org2[0] - width * right2[0];
7278 vert[ 7] = org2[1] - width * right2[1];
7279 vert[ 8] = org2[2] - width * right2[2];
7280 vert[ 9] = org2[0] + width * right2[0];
7281 vert[10] = org2[1] + width * right2[1];
7282 vert[11] = org2[2] + width * right2[2];
7285 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)
7287 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7288 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7289 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7290 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7291 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7292 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7293 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7294 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7295 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7296 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7297 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7298 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7301 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7306 VectorSet(v, x, y, z);
7307 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7308 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7310 if (i == mesh->numvertices)
7312 if (mesh->numvertices < mesh->maxvertices)
7314 VectorCopy(v, vertex3f);
7315 mesh->numvertices++;
7317 return mesh->numvertices;
7323 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7327 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7328 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7329 e = mesh->element3i + mesh->numtriangles * 3;
7330 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7332 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7333 if (mesh->numtriangles < mesh->maxtriangles)
7338 mesh->numtriangles++;
7340 element[1] = element[2];
7344 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7348 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7349 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7350 e = mesh->element3i + mesh->numtriangles * 3;
7351 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7353 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7354 if (mesh->numtriangles < mesh->maxtriangles)
7359 mesh->numtriangles++;
7361 element[1] = element[2];
7365 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7366 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7368 int planenum, planenum2;
7371 mplane_t *plane, *plane2;
7373 double temppoints[2][256*3];
7374 // figure out how large a bounding box we need to properly compute this brush
7376 for (w = 0;w < numplanes;w++)
7377 maxdist = max(maxdist, fabs(planes[w].dist));
7378 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7379 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7380 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7384 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7385 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7387 if (planenum2 == planenum)
7389 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);
7392 if (tempnumpoints < 3)
7394 // generate elements forming a triangle fan for this polygon
7395 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7399 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)
7401 texturelayer_t *layer;
7402 layer = t->currentlayers + t->currentnumlayers++;
7404 layer->depthmask = depthmask;
7405 layer->blendfunc1 = blendfunc1;
7406 layer->blendfunc2 = blendfunc2;
7407 layer->texture = texture;
7408 layer->texmatrix = *matrix;
7409 layer->color[0] = r;
7410 layer->color[1] = g;
7411 layer->color[2] = b;
7412 layer->color[3] = a;
7415 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7417 if(parms[0] == 0 && parms[1] == 0)
7419 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7420 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7425 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7428 index = parms[2] + rsurface.shadertime * parms[3];
7429 index -= floor(index);
7430 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7433 case Q3WAVEFUNC_NONE:
7434 case Q3WAVEFUNC_NOISE:
7435 case Q3WAVEFUNC_COUNT:
7438 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7439 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7440 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7441 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7442 case Q3WAVEFUNC_TRIANGLE:
7444 f = index - floor(index);
7455 f = parms[0] + parms[1] * f;
7456 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7457 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7461 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7467 matrix4x4_t matrix, temp;
7468 switch(tcmod->tcmod)
7472 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7473 matrix = r_waterscrollmatrix;
7475 matrix = identitymatrix;
7477 case Q3TCMOD_ENTITYTRANSLATE:
7478 // this is used in Q3 to allow the gamecode to control texcoord
7479 // scrolling on the entity, which is not supported in darkplaces yet.
7480 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7482 case Q3TCMOD_ROTATE:
7483 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7484 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
7485 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7488 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7490 case Q3TCMOD_SCROLL:
7491 // extra care is needed because of precision breakdown with large values of time
7492 offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7493 offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7494 Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7496 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7497 w = (int) tcmod->parms[0];
7498 h = (int) tcmod->parms[1];
7499 f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7501 idx = (int) floor(f * w * h);
7502 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7504 case Q3TCMOD_STRETCH:
7505 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7506 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7508 case Q3TCMOD_TRANSFORM:
7509 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
7510 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
7511 VectorSet(tcmat + 6, 0 , 0 , 1);
7512 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
7513 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7515 case Q3TCMOD_TURBULENT:
7516 // this is handled in the RSurf_PrepareVertices function
7517 matrix = identitymatrix;
7521 Matrix4x4_Concat(texmatrix, &matrix, &temp);
7524 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7526 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7527 char name[MAX_QPATH];
7528 skinframe_t *skinframe;
7529 unsigned char pixels[296*194];
7530 strlcpy(cache->name, skinname, sizeof(cache->name));
7531 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7532 if (developer_loading.integer)
7533 Con_Printf("loading %s\n", name);
7534 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7535 if (!skinframe || !skinframe->base)
7538 fs_offset_t filesize;
7540 f = FS_LoadFile(name, tempmempool, true, &filesize);
7543 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7544 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7548 cache->skinframe = skinframe;
7551 texture_t *R_GetCurrentTexture(texture_t *t)
7554 const entity_render_t *ent = rsurface.entity;
7555 dp_model_t *model = ent->model;
7556 q3shaderinfo_layer_tcmod_t *tcmod;
7558 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7559 return t->currentframe;
7560 t->update_lastrenderframe = r_textureframe;
7561 t->update_lastrenderentity = (void *)ent;
7563 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7564 t->camera_entity = ent->entitynumber;
7566 t->camera_entity = 0;
7568 // switch to an alternate material if this is a q1bsp animated material
7570 texture_t *texture = t;
7571 int s = rsurface.ent_skinnum;
7572 if ((unsigned int)s >= (unsigned int)model->numskins)
7574 if (model->skinscenes)
7576 if (model->skinscenes[s].framecount > 1)
7577 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7579 s = model->skinscenes[s].firstframe;
7582 t = t + s * model->num_surfaces;
7585 // use an alternate animation if the entity's frame is not 0,
7586 // and only if the texture has an alternate animation
7587 if (rsurface.ent_alttextures && t->anim_total[1])
7588 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7590 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7592 texture->currentframe = t;
7595 // update currentskinframe to be a qw skin or animation frame
7596 if (rsurface.ent_qwskin >= 0)
7598 i = rsurface.ent_qwskin;
7599 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7601 r_qwskincache_size = cl.maxclients;
7603 Mem_Free(r_qwskincache);
7604 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7606 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7607 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7608 t->currentskinframe = r_qwskincache[i].skinframe;
7609 if (t->currentskinframe == NULL)
7610 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7612 else if (t->numskinframes >= 2)
7613 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7614 if (t->backgroundnumskinframes >= 2)
7615 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7617 t->currentmaterialflags = t->basematerialflags;
7618 t->currentalpha = rsurface.colormod[3];
7619 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7620 t->currentalpha *= r_wateralpha.value;
7621 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7622 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7623 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7624 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7625 if (!(rsurface.ent_flags & RENDER_LIGHT))
7626 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7627 else if (FAKELIGHT_ENABLED)
7629 // no modellight if using fakelight for the map
7631 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7633 // pick a model lighting mode
7634 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7635 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7637 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7639 if (rsurface.ent_flags & RENDER_ADDITIVE)
7640 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7641 else if (t->currentalpha < 1)
7642 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7643 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7644 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7645 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7646 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7647 if (t->backgroundnumskinframes)
7648 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7649 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7651 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7652 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7655 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7656 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7657 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7659 // there is no tcmod
7660 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7662 t->currenttexmatrix = r_waterscrollmatrix;
7663 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7665 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7667 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7668 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7671 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7672 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7673 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7674 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7676 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7677 if (t->currentskinframe->qpixels)
7678 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7679 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7680 if (!t->basetexture)
7681 t->basetexture = r_texture_notexture;
7682 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7683 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7684 t->nmaptexture = t->currentskinframe->nmap;
7685 if (!t->nmaptexture)
7686 t->nmaptexture = r_texture_blanknormalmap;
7687 t->glosstexture = r_texture_black;
7688 t->glowtexture = t->currentskinframe->glow;
7689 t->fogtexture = t->currentskinframe->fog;
7690 t->reflectmasktexture = t->currentskinframe->reflect;
7691 if (t->backgroundnumskinframes)
7693 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7694 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7695 t->backgroundglosstexture = r_texture_black;
7696 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7697 if (!t->backgroundnmaptexture)
7698 t->backgroundnmaptexture = r_texture_blanknormalmap;
7702 t->backgroundbasetexture = r_texture_white;
7703 t->backgroundnmaptexture = r_texture_blanknormalmap;
7704 t->backgroundglosstexture = r_texture_black;
7705 t->backgroundglowtexture = NULL;
7707 t->specularpower = r_shadow_glossexponent.value;
7708 // TODO: store reference values for these in the texture?
7709 t->specularscale = 0;
7710 if (r_shadow_gloss.integer > 0)
7712 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7714 if (r_shadow_glossintensity.value > 0)
7716 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7717 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7718 t->specularscale = r_shadow_glossintensity.value;
7721 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7723 t->glosstexture = r_texture_white;
7724 t->backgroundglosstexture = r_texture_white;
7725 t->specularscale = r_shadow_gloss2intensity.value;
7726 t->specularpower = r_shadow_gloss2exponent.value;
7729 t->specularscale *= t->specularscalemod;
7730 t->specularpower *= t->specularpowermod;
7732 // lightmaps mode looks bad with dlights using actual texturing, so turn
7733 // off the colormap and glossmap, but leave the normalmap on as it still
7734 // accurately represents the shading involved
7735 if (gl_lightmaps.integer)
7737 t->basetexture = r_texture_grey128;
7738 t->pantstexture = r_texture_black;
7739 t->shirttexture = r_texture_black;
7740 t->nmaptexture = r_texture_blanknormalmap;
7741 t->glosstexture = r_texture_black;
7742 t->glowtexture = NULL;
7743 t->fogtexture = NULL;
7744 t->reflectmasktexture = NULL;
7745 t->backgroundbasetexture = NULL;
7746 t->backgroundnmaptexture = r_texture_blanknormalmap;
7747 t->backgroundglosstexture = r_texture_black;
7748 t->backgroundglowtexture = NULL;
7749 t->specularscale = 0;
7750 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7753 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7754 VectorClear(t->dlightcolor);
7755 t->currentnumlayers = 0;
7756 if (t->currentmaterialflags & MATERIALFLAG_WALL)
7758 int blendfunc1, blendfunc2;
7760 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7762 blendfunc1 = GL_SRC_ALPHA;
7763 blendfunc2 = GL_ONE;
7765 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7767 blendfunc1 = GL_SRC_ALPHA;
7768 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7770 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7772 blendfunc1 = t->customblendfunc[0];
7773 blendfunc2 = t->customblendfunc[1];
7777 blendfunc1 = GL_ONE;
7778 blendfunc2 = GL_ZERO;
7780 // don't colormod evilblend textures
7781 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7782 VectorSet(t->lightmapcolor, 1, 1, 1);
7783 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7784 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7786 // fullbright is not affected by r_refdef.lightmapintensity
7787 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]);
7788 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7789 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]);
7790 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7791 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]);
7795 vec3_t ambientcolor;
7797 // set the color tint used for lights affecting this surface
7798 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7800 // q3bsp has no lightmap updates, so the lightstylevalue that
7801 // would normally be baked into the lightmap must be
7802 // applied to the color
7803 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7804 if (model->type == mod_brushq3)
7805 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7806 colorscale *= r_refdef.lightmapintensity;
7807 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7808 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7809 // basic lit geometry
7810 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]);
7811 // add pants/shirt if needed
7812 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7813 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]);
7814 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7815 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]);
7816 // now add ambient passes if needed
7817 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7819 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]);
7820 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7821 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]);
7822 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7823 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]);
7826 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7827 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]);
7828 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7830 // if this is opaque use alpha blend which will darken the earlier
7833 // if this is an alpha blended material, all the earlier passes
7834 // were darkened by fog already, so we only need to add the fog
7835 // color ontop through the fog mask texture
7837 // if this is an additive blended material, all the earlier passes
7838 // were darkened by fog already, and we should not add fog color
7839 // (because the background was not darkened, there is no fog color
7840 // that was lost behind it).
7841 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]);
7845 return t->currentframe;
7848 rsurfacestate_t rsurface;
7850 void RSurf_ActiveWorldEntity(void)
7852 dp_model_t *model = r_refdef.scene.worldmodel;
7853 //if (rsurface.entity == r_refdef.scene.worldentity)
7855 rsurface.entity = r_refdef.scene.worldentity;
7856 rsurface.skeleton = NULL;
7857 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7858 rsurface.ent_skinnum = 0;
7859 rsurface.ent_qwskin = -1;
7860 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7861 rsurface.shadertime = r_refdef.scene.time;
7862 rsurface.matrix = identitymatrix;
7863 rsurface.inversematrix = identitymatrix;
7864 rsurface.matrixscale = 1;
7865 rsurface.inversematrixscale = 1;
7866 R_EntityMatrix(&identitymatrix);
7867 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7868 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7869 rsurface.fograngerecip = r_refdef.fograngerecip;
7870 rsurface.fogheightfade = r_refdef.fogheightfade;
7871 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7872 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7873 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7874 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7875 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7876 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7877 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7878 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7879 rsurface.colormod[3] = 1;
7880 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);
7881 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7882 rsurface.frameblend[0].lerp = 1;
7883 rsurface.ent_alttextures = false;
7884 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7885 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7886 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7887 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7888 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7889 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7890 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7891 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7892 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7893 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7894 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7895 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7896 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7897 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7898 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7899 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7900 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7901 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7902 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7903 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7904 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7905 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7906 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7907 rsurface.modelelement3i = model->surfmesh.data_element3i;
7908 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7909 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7910 rsurface.modelelement3s = model->surfmesh.data_element3s;
7911 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7912 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7913 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7914 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7915 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7916 rsurface.modelsurfaces = model->data_surfaces;
7917 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7918 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7919 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7920 rsurface.modelgeneratedvertex = false;
7921 rsurface.batchgeneratedvertex = false;
7922 rsurface.batchfirstvertex = 0;
7923 rsurface.batchnumvertices = 0;
7924 rsurface.batchfirsttriangle = 0;
7925 rsurface.batchnumtriangles = 0;
7926 rsurface.batchvertex3f = NULL;
7927 rsurface.batchvertex3f_vertexbuffer = NULL;
7928 rsurface.batchvertex3f_bufferoffset = 0;
7929 rsurface.batchsvector3f = NULL;
7930 rsurface.batchsvector3f_vertexbuffer = NULL;
7931 rsurface.batchsvector3f_bufferoffset = 0;
7932 rsurface.batchtvector3f = NULL;
7933 rsurface.batchtvector3f_vertexbuffer = NULL;
7934 rsurface.batchtvector3f_bufferoffset = 0;
7935 rsurface.batchnormal3f = NULL;
7936 rsurface.batchnormal3f_vertexbuffer = NULL;
7937 rsurface.batchnormal3f_bufferoffset = 0;
7938 rsurface.batchlightmapcolor4f = NULL;
7939 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7940 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7941 rsurface.batchtexcoordtexture2f = NULL;
7942 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7943 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7944 rsurface.batchtexcoordlightmap2f = NULL;
7945 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7946 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7947 rsurface.batchvertexmesh = NULL;
7948 rsurface.batchvertexmeshbuffer = NULL;
7949 rsurface.batchvertex3fbuffer = NULL;
7950 rsurface.batchelement3i = NULL;
7951 rsurface.batchelement3i_indexbuffer = NULL;
7952 rsurface.batchelement3i_bufferoffset = 0;
7953 rsurface.batchelement3s = NULL;
7954 rsurface.batchelement3s_indexbuffer = NULL;
7955 rsurface.batchelement3s_bufferoffset = 0;
7956 rsurface.passcolor4f = NULL;
7957 rsurface.passcolor4f_vertexbuffer = NULL;
7958 rsurface.passcolor4f_bufferoffset = 0;
7961 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7963 dp_model_t *model = ent->model;
7964 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7966 rsurface.entity = (entity_render_t *)ent;
7967 rsurface.skeleton = ent->skeleton;
7968 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7969 rsurface.ent_skinnum = ent->skinnum;
7970 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;
7971 rsurface.ent_flags = ent->flags;
7972 rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
7973 rsurface.matrix = ent->matrix;
7974 rsurface.inversematrix = ent->inversematrix;
7975 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7976 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7977 R_EntityMatrix(&rsurface.matrix);
7978 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7979 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7980 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7981 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7982 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7983 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7984 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7985 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7986 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7987 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7988 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7989 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7990 rsurface.colormod[3] = ent->alpha;
7991 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7992 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7993 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7994 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7995 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7996 if (ent->model->brush.submodel && !prepass)
7998 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7999 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8001 if (model->surfmesh.isanimated && model->AnimateVertices)
8003 if (ent->animcache_vertex3f)
8005 rsurface.modelvertex3f = ent->animcache_vertex3f;
8006 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8007 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8008 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8009 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8010 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8011 rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8013 else if (wanttangents)
8015 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8016 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8017 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8018 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8019 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8020 rsurface.modelvertexmesh = NULL;
8021 rsurface.modelvertexmeshbuffer = NULL;
8022 rsurface.modelvertex3fbuffer = NULL;
8024 else if (wantnormals)
8026 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8027 rsurface.modelsvector3f = NULL;
8028 rsurface.modeltvector3f = NULL;
8029 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8030 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8031 rsurface.modelvertexmesh = NULL;
8032 rsurface.modelvertexmeshbuffer = NULL;
8033 rsurface.modelvertex3fbuffer = NULL;
8037 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8038 rsurface.modelsvector3f = NULL;
8039 rsurface.modeltvector3f = NULL;
8040 rsurface.modelnormal3f = NULL;
8041 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8042 rsurface.modelvertexmesh = NULL;
8043 rsurface.modelvertexmeshbuffer = NULL;
8044 rsurface.modelvertex3fbuffer = NULL;
8046 rsurface.modelvertex3f_vertexbuffer = 0;
8047 rsurface.modelvertex3f_bufferoffset = 0;
8048 rsurface.modelsvector3f_vertexbuffer = 0;
8049 rsurface.modelsvector3f_bufferoffset = 0;
8050 rsurface.modeltvector3f_vertexbuffer = 0;
8051 rsurface.modeltvector3f_bufferoffset = 0;
8052 rsurface.modelnormal3f_vertexbuffer = 0;
8053 rsurface.modelnormal3f_bufferoffset = 0;
8054 rsurface.modelgeneratedvertex = true;
8058 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8059 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8060 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8061 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8062 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8063 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8064 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8065 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8066 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8067 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8068 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8069 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8070 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8071 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8072 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8073 rsurface.modelgeneratedvertex = false;
8075 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8076 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8077 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8078 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8079 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8080 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8081 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8082 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8083 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8084 rsurface.modelelement3i = model->surfmesh.data_element3i;
8085 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8086 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8087 rsurface.modelelement3s = model->surfmesh.data_element3s;
8088 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8089 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8090 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8091 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8092 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8093 rsurface.modelsurfaces = model->data_surfaces;
8094 rsurface.batchgeneratedvertex = false;
8095 rsurface.batchfirstvertex = 0;
8096 rsurface.batchnumvertices = 0;
8097 rsurface.batchfirsttriangle = 0;
8098 rsurface.batchnumtriangles = 0;
8099 rsurface.batchvertex3f = NULL;
8100 rsurface.batchvertex3f_vertexbuffer = NULL;
8101 rsurface.batchvertex3f_bufferoffset = 0;
8102 rsurface.batchsvector3f = NULL;
8103 rsurface.batchsvector3f_vertexbuffer = NULL;
8104 rsurface.batchsvector3f_bufferoffset = 0;
8105 rsurface.batchtvector3f = NULL;
8106 rsurface.batchtvector3f_vertexbuffer = NULL;
8107 rsurface.batchtvector3f_bufferoffset = 0;
8108 rsurface.batchnormal3f = NULL;
8109 rsurface.batchnormal3f_vertexbuffer = NULL;
8110 rsurface.batchnormal3f_bufferoffset = 0;
8111 rsurface.batchlightmapcolor4f = NULL;
8112 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8113 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8114 rsurface.batchtexcoordtexture2f = NULL;
8115 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8116 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8117 rsurface.batchtexcoordlightmap2f = NULL;
8118 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8119 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8120 rsurface.batchvertexmesh = NULL;
8121 rsurface.batchvertexmeshbuffer = NULL;
8122 rsurface.batchvertex3fbuffer = NULL;
8123 rsurface.batchelement3i = NULL;
8124 rsurface.batchelement3i_indexbuffer = NULL;
8125 rsurface.batchelement3i_bufferoffset = 0;
8126 rsurface.batchelement3s = NULL;
8127 rsurface.batchelement3s_indexbuffer = NULL;
8128 rsurface.batchelement3s_bufferoffset = 0;
8129 rsurface.passcolor4f = NULL;
8130 rsurface.passcolor4f_vertexbuffer = NULL;
8131 rsurface.passcolor4f_bufferoffset = 0;
8134 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)
8136 rsurface.entity = r_refdef.scene.worldentity;
8137 rsurface.skeleton = NULL;
8138 rsurface.ent_skinnum = 0;
8139 rsurface.ent_qwskin = -1;
8140 rsurface.ent_flags = entflags;
8141 rsurface.shadertime = r_refdef.scene.time - shadertime;
8142 rsurface.modelnumvertices = numvertices;
8143 rsurface.modelnumtriangles = numtriangles;
8144 rsurface.matrix = *matrix;
8145 rsurface.inversematrix = *inversematrix;
8146 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8147 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8148 R_EntityMatrix(&rsurface.matrix);
8149 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8150 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8151 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8152 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8153 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8154 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8155 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8156 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8157 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8158 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8159 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8160 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8161 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);
8162 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8163 rsurface.frameblend[0].lerp = 1;
8164 rsurface.ent_alttextures = false;
8165 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8166 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8169 rsurface.modelvertex3f = (float *)vertex3f;
8170 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8171 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8172 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8174 else if (wantnormals)
8176 rsurface.modelvertex3f = (float *)vertex3f;
8177 rsurface.modelsvector3f = NULL;
8178 rsurface.modeltvector3f = NULL;
8179 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8183 rsurface.modelvertex3f = (float *)vertex3f;
8184 rsurface.modelsvector3f = NULL;
8185 rsurface.modeltvector3f = NULL;
8186 rsurface.modelnormal3f = NULL;
8188 rsurface.modelvertexmesh = NULL;
8189 rsurface.modelvertexmeshbuffer = NULL;
8190 rsurface.modelvertex3fbuffer = NULL;
8191 rsurface.modelvertex3f_vertexbuffer = 0;
8192 rsurface.modelvertex3f_bufferoffset = 0;
8193 rsurface.modelsvector3f_vertexbuffer = 0;
8194 rsurface.modelsvector3f_bufferoffset = 0;
8195 rsurface.modeltvector3f_vertexbuffer = 0;
8196 rsurface.modeltvector3f_bufferoffset = 0;
8197 rsurface.modelnormal3f_vertexbuffer = 0;
8198 rsurface.modelnormal3f_bufferoffset = 0;
8199 rsurface.modelgeneratedvertex = true;
8200 rsurface.modellightmapcolor4f = (float *)color4f;
8201 rsurface.modellightmapcolor4f_vertexbuffer = 0;
8202 rsurface.modellightmapcolor4f_bufferoffset = 0;
8203 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
8204 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8205 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8206 rsurface.modeltexcoordlightmap2f = NULL;
8207 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8208 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8209 rsurface.modelelement3i = (int *)element3i;
8210 rsurface.modelelement3i_indexbuffer = NULL;
8211 rsurface.modelelement3i_bufferoffset = 0;
8212 rsurface.modelelement3s = (unsigned short *)element3s;
8213 rsurface.modelelement3s_indexbuffer = NULL;
8214 rsurface.modelelement3s_bufferoffset = 0;
8215 rsurface.modellightmapoffsets = NULL;
8216 rsurface.modelsurfaces = NULL;
8217 rsurface.batchgeneratedvertex = false;
8218 rsurface.batchfirstvertex = 0;
8219 rsurface.batchnumvertices = 0;
8220 rsurface.batchfirsttriangle = 0;
8221 rsurface.batchnumtriangles = 0;
8222 rsurface.batchvertex3f = NULL;
8223 rsurface.batchvertex3f_vertexbuffer = NULL;
8224 rsurface.batchvertex3f_bufferoffset = 0;
8225 rsurface.batchsvector3f = NULL;
8226 rsurface.batchsvector3f_vertexbuffer = NULL;
8227 rsurface.batchsvector3f_bufferoffset = 0;
8228 rsurface.batchtvector3f = NULL;
8229 rsurface.batchtvector3f_vertexbuffer = NULL;
8230 rsurface.batchtvector3f_bufferoffset = 0;
8231 rsurface.batchnormal3f = NULL;
8232 rsurface.batchnormal3f_vertexbuffer = NULL;
8233 rsurface.batchnormal3f_bufferoffset = 0;
8234 rsurface.batchlightmapcolor4f = NULL;
8235 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8236 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8237 rsurface.batchtexcoordtexture2f = NULL;
8238 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8239 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8240 rsurface.batchtexcoordlightmap2f = NULL;
8241 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8242 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8243 rsurface.batchvertexmesh = NULL;
8244 rsurface.batchvertexmeshbuffer = NULL;
8245 rsurface.batchvertex3fbuffer = NULL;
8246 rsurface.batchelement3i = NULL;
8247 rsurface.batchelement3i_indexbuffer = NULL;
8248 rsurface.batchelement3i_bufferoffset = 0;
8249 rsurface.batchelement3s = NULL;
8250 rsurface.batchelement3s_indexbuffer = NULL;
8251 rsurface.batchelement3s_bufferoffset = 0;
8252 rsurface.passcolor4f = NULL;
8253 rsurface.passcolor4f_vertexbuffer = NULL;
8254 rsurface.passcolor4f_bufferoffset = 0;
8256 if (rsurface.modelnumvertices && rsurface.modelelement3i)
8258 if ((wantnormals || wanttangents) && !normal3f)
8260 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8261 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8263 if (wanttangents && !svector3f)
8265 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8266 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8267 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8272 float RSurf_FogPoint(const float *v)
8274 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8275 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8276 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8277 float FogHeightFade = r_refdef.fogheightfade;
8279 unsigned int fogmasktableindex;
8280 if (r_refdef.fogplaneviewabove)
8281 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8283 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8284 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8285 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8288 float RSurf_FogVertex(const float *v)
8290 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8291 float FogPlaneViewDist = rsurface.fogplaneviewdist;
8292 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8293 float FogHeightFade = rsurface.fogheightfade;
8295 unsigned int fogmasktableindex;
8296 if (r_refdef.fogplaneviewabove)
8297 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8299 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8300 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8301 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8304 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8307 for (i = 0;i < numelements;i++)
8308 outelement3i[i] = inelement3i[i] + adjust;
8311 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8312 extern cvar_t gl_vbo;
8313 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8321 int surfacefirsttriangle;
8322 int surfacenumtriangles;
8323 int surfacefirstvertex;
8324 int surfaceendvertex;
8325 int surfacenumvertices;
8326 int batchnumvertices;
8327 int batchnumtriangles;
8331 qboolean dynamicvertex;
8335 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8337 q3shaderinfo_deform_t *deform;
8338 const msurface_t *surface, *firstsurface;
8339 r_vertexmesh_t *vertexmesh;
8340 if (!texturenumsurfaces)
8342 // find vertex range of this surface batch
8344 firstsurface = texturesurfacelist[0];
8345 firsttriangle = firstsurface->num_firsttriangle;
8346 batchnumvertices = 0;
8347 batchnumtriangles = 0;
8348 firstvertex = endvertex = firstsurface->num_firstvertex;
8349 for (i = 0;i < texturenumsurfaces;i++)
8351 surface = texturesurfacelist[i];
8352 if (surface != firstsurface + i)
8354 surfacefirstvertex = surface->num_firstvertex;
8355 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8356 surfacenumvertices = surface->num_vertices;
8357 surfacenumtriangles = surface->num_triangles;
8358 if (firstvertex > surfacefirstvertex)
8359 firstvertex = surfacefirstvertex;
8360 if (endvertex < surfaceendvertex)
8361 endvertex = surfaceendvertex;
8362 batchnumvertices += surfacenumvertices;
8363 batchnumtriangles += surfacenumtriangles;
8366 // we now know the vertex range used, and if there are any gaps in it
8367 rsurface.batchfirstvertex = firstvertex;
8368 rsurface.batchnumvertices = endvertex - firstvertex;
8369 rsurface.batchfirsttriangle = firsttriangle;
8370 rsurface.batchnumtriangles = batchnumtriangles;
8372 // this variable holds flags for which properties have been updated that
8373 // may require regenerating vertexmesh array...
8376 // check if any dynamic vertex processing must occur
8377 dynamicvertex = false;
8379 // if there is a chance of animated vertex colors, it's a dynamic batch
8380 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8382 dynamicvertex = true;
8383 batchneed |= BATCHNEED_NOGAPS;
8384 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8387 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8389 switch (deform->deform)
8392 case Q3DEFORM_PROJECTIONSHADOW:
8393 case Q3DEFORM_TEXT0:
8394 case Q3DEFORM_TEXT1:
8395 case Q3DEFORM_TEXT2:
8396 case Q3DEFORM_TEXT3:
8397 case Q3DEFORM_TEXT4:
8398 case Q3DEFORM_TEXT5:
8399 case Q3DEFORM_TEXT6:
8400 case Q3DEFORM_TEXT7:
8403 case Q3DEFORM_AUTOSPRITE:
8404 dynamicvertex = true;
8405 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8406 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8408 case Q3DEFORM_AUTOSPRITE2:
8409 dynamicvertex = true;
8410 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8411 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8413 case Q3DEFORM_NORMAL:
8414 dynamicvertex = true;
8415 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8416 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8419 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8420 break; // if wavefunc is a nop, ignore this transform
8421 dynamicvertex = true;
8422 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8423 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8425 case Q3DEFORM_BULGE:
8426 dynamicvertex = true;
8427 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8428 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8431 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8432 break; // if wavefunc is a nop, ignore this transform
8433 dynamicvertex = true;
8434 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8435 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8439 switch(rsurface.texture->tcgen.tcgen)
8442 case Q3TCGEN_TEXTURE:
8444 case Q3TCGEN_LIGHTMAP:
8445 dynamicvertex = true;
8446 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8447 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8449 case Q3TCGEN_VECTOR:
8450 dynamicvertex = true;
8451 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8452 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8454 case Q3TCGEN_ENVIRONMENT:
8455 dynamicvertex = true;
8456 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8457 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8460 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8462 dynamicvertex = true;
8463 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8464 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8467 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8469 dynamicvertex = true;
8470 batchneed |= BATCHNEED_NOGAPS;
8471 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8474 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8476 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8477 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
8478 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
8479 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
8480 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8481 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8482 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8485 // when the model data has no vertex buffer (dynamic mesh), we need to
8487 if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8488 batchneed |= BATCHNEED_NOGAPS;
8490 // if needsupdate, we have to do a dynamic vertex batch for sure
8491 if (needsupdate & batchneed)
8492 dynamicvertex = true;
8494 // see if we need to build vertexmesh from arrays
8495 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8496 dynamicvertex = true;
8498 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8499 // also some drivers strongly dislike firstvertex
8500 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8501 dynamicvertex = true;
8503 rsurface.batchvertex3f = rsurface.modelvertex3f;
8504 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8505 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8506 rsurface.batchsvector3f = rsurface.modelsvector3f;
8507 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8508 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8509 rsurface.batchtvector3f = rsurface.modeltvector3f;
8510 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8511 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8512 rsurface.batchnormal3f = rsurface.modelnormal3f;
8513 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8514 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8515 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8516 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
8517 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8518 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8519 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
8520 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
8521 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8522 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8523 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8524 rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8525 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8526 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8527 rsurface.batchelement3i = rsurface.modelelement3i;
8528 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8529 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8530 rsurface.batchelement3s = rsurface.modelelement3s;
8531 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8532 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8534 // if any dynamic vertex processing has to occur in software, we copy the
8535 // entire surface list together before processing to rebase the vertices
8536 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8538 // if any gaps exist and we do not have a static vertex buffer, we have to
8539 // copy the surface list together to avoid wasting upload bandwidth on the
8540 // vertices in the gaps.
8542 // if gaps exist and we have a static vertex buffer, we still have to
8543 // combine the index buffer ranges into one dynamic index buffer.
8545 // in all cases we end up with data that can be drawn in one call.
8549 // static vertex data, just set pointers...
8550 rsurface.batchgeneratedvertex = false;
8551 // if there are gaps, we want to build a combined index buffer,
8552 // otherwise use the original static buffer with an appropriate offset
8555 // build a new triangle elements array for this batch
8556 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8557 rsurface.batchfirsttriangle = 0;
8559 for (i = 0;i < texturenumsurfaces;i++)
8561 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8562 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8563 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8564 numtriangles += surfacenumtriangles;
8566 rsurface.batchelement3i_indexbuffer = NULL;
8567 rsurface.batchelement3i_bufferoffset = 0;
8568 rsurface.batchelement3s = NULL;
8569 rsurface.batchelement3s_indexbuffer = NULL;
8570 rsurface.batchelement3s_bufferoffset = 0;
8571 if (endvertex <= 65536)
8573 // make a 16bit (unsigned short) index array if possible
8574 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8575 for (i = 0;i < numtriangles*3;i++)
8576 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8582 // something needs software processing, do it for real...
8583 // we only directly handle separate array data in this case and then
8584 // generate interleaved data if needed...
8585 rsurface.batchgeneratedvertex = true;
8587 // now copy the vertex data into a combined array and make an index array
8588 // (this is what Quake3 does all the time)
8589 //if (gaps || rsurface.batchfirstvertex)
8591 rsurface.batchvertex3fbuffer = NULL;
8592 rsurface.batchvertexmesh = NULL;
8593 rsurface.batchvertexmeshbuffer = NULL;
8594 rsurface.batchvertex3f = NULL;
8595 rsurface.batchvertex3f_vertexbuffer = NULL;
8596 rsurface.batchvertex3f_bufferoffset = 0;
8597 rsurface.batchsvector3f = NULL;
8598 rsurface.batchsvector3f_vertexbuffer = NULL;
8599 rsurface.batchsvector3f_bufferoffset = 0;
8600 rsurface.batchtvector3f = NULL;
8601 rsurface.batchtvector3f_vertexbuffer = NULL;
8602 rsurface.batchtvector3f_bufferoffset = 0;
8603 rsurface.batchnormal3f = NULL;
8604 rsurface.batchnormal3f_vertexbuffer = NULL;
8605 rsurface.batchnormal3f_bufferoffset = 0;
8606 rsurface.batchlightmapcolor4f = NULL;
8607 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8608 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8609 rsurface.batchtexcoordtexture2f = NULL;
8610 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8611 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8612 rsurface.batchtexcoordlightmap2f = NULL;
8613 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8614 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8615 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8616 rsurface.batchelement3i_indexbuffer = NULL;
8617 rsurface.batchelement3i_bufferoffset = 0;
8618 rsurface.batchelement3s = NULL;
8619 rsurface.batchelement3s_indexbuffer = NULL;
8620 rsurface.batchelement3s_bufferoffset = 0;
8621 // we'll only be setting up certain arrays as needed
8622 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8623 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8624 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8625 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8626 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8627 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8628 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8630 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8631 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8633 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8634 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8635 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8636 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8637 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8638 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8641 for (i = 0;i < texturenumsurfaces;i++)
8643 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8644 surfacenumvertices = texturesurfacelist[i]->num_vertices;
8645 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8646 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8647 // copy only the data requested
8648 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8649 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8650 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8652 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8654 if (rsurface.batchvertex3f)
8655 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8657 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8659 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8661 if (rsurface.modelnormal3f)
8662 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8664 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8666 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8668 if (rsurface.modelsvector3f)
8670 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8671 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8675 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8676 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8679 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8681 if (rsurface.modellightmapcolor4f)
8682 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8684 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
8686 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8688 if (rsurface.modeltexcoordtexture2f)
8689 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8691 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8693 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8695 if (rsurface.modeltexcoordlightmap2f)
8696 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8698 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8701 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8702 numvertices += surfacenumvertices;
8703 numtriangles += surfacenumtriangles;
8706 // generate a 16bit index array as well if possible
8707 // (in general, dynamic batches fit)
8708 if (numvertices <= 65536)
8710 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8711 for (i = 0;i < numtriangles*3;i++)
8712 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8715 // since we've copied everything, the batch now starts at 0
8716 rsurface.batchfirstvertex = 0;
8717 rsurface.batchnumvertices = batchnumvertices;
8718 rsurface.batchfirsttriangle = 0;
8719 rsurface.batchnumtriangles = batchnumtriangles;
8722 // q1bsp surfaces rendered in vertex color mode have to have colors
8723 // calculated based on lightstyles
8724 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8726 // generate color arrays for the surfaces in this list
8731 const unsigned char *lm;
8732 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8733 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8734 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8736 for (i = 0;i < texturenumsurfaces;i++)
8738 surface = texturesurfacelist[i];
8739 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8740 surfacenumvertices = surface->num_vertices;
8741 if (surface->lightmapinfo->samples)
8743 for (j = 0;j < surfacenumvertices;j++)
8745 lm = surface->lightmapinfo->samples + offsets[j];
8746 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8747 VectorScale(lm, scale, c);
8748 if (surface->lightmapinfo->styles[1] != 255)
8750 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8752 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8753 VectorMA(c, scale, lm, c);
8754 if (surface->lightmapinfo->styles[2] != 255)
8757 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8758 VectorMA(c, scale, lm, c);
8759 if (surface->lightmapinfo->styles[3] != 255)
8762 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8763 VectorMA(c, scale, lm, c);
8770 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);
8776 for (j = 0;j < surfacenumvertices;j++)
8778 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8785 // if vertices are deformed (sprite flares and things in maps, possibly
8786 // water waves, bulges and other deformations), modify the copied vertices
8788 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8790 switch (deform->deform)
8793 case Q3DEFORM_PROJECTIONSHADOW:
8794 case Q3DEFORM_TEXT0:
8795 case Q3DEFORM_TEXT1:
8796 case Q3DEFORM_TEXT2:
8797 case Q3DEFORM_TEXT3:
8798 case Q3DEFORM_TEXT4:
8799 case Q3DEFORM_TEXT5:
8800 case Q3DEFORM_TEXT6:
8801 case Q3DEFORM_TEXT7:
8804 case Q3DEFORM_AUTOSPRITE:
8805 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8806 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8807 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8808 VectorNormalize(newforward);
8809 VectorNormalize(newright);
8810 VectorNormalize(newup);
8811 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8812 // rsurface.batchvertex3f_vertexbuffer = NULL;
8813 // rsurface.batchvertex3f_bufferoffset = 0;
8814 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8815 // rsurface.batchsvector3f_vertexbuffer = NULL;
8816 // rsurface.batchsvector3f_bufferoffset = 0;
8817 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8818 // rsurface.batchtvector3f_vertexbuffer = NULL;
8819 // rsurface.batchtvector3f_bufferoffset = 0;
8820 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8821 // rsurface.batchnormal3f_vertexbuffer = NULL;
8822 // rsurface.batchnormal3f_bufferoffset = 0;
8823 // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
8824 if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
8825 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8826 if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
8827 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);
8828 // a single autosprite surface can contain multiple sprites...
8829 for (j = 0;j < batchnumvertices - 3;j += 4)
8831 VectorClear(center);
8832 for (i = 0;i < 4;i++)
8833 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8834 VectorScale(center, 0.25f, center);
8835 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8836 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8837 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8838 for (i = 0;i < 4;i++)
8840 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8841 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8844 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8845 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8846 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);
8848 case Q3DEFORM_AUTOSPRITE2:
8849 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8850 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8851 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8852 VectorNormalize(newforward);
8853 VectorNormalize(newright);
8854 VectorNormalize(newup);
8855 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8856 // rsurface.batchvertex3f_vertexbuffer = NULL;
8857 // rsurface.batchvertex3f_bufferoffset = 0;
8859 const float *v1, *v2;
8869 memset(shortest, 0, sizeof(shortest));
8870 // a single autosprite surface can contain multiple sprites...
8871 for (j = 0;j < batchnumvertices - 3;j += 4)
8873 VectorClear(center);
8874 for (i = 0;i < 4;i++)
8875 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8876 VectorScale(center, 0.25f, center);
8877 // find the two shortest edges, then use them to define the
8878 // axis vectors for rotating around the central axis
8879 for (i = 0;i < 6;i++)
8881 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8882 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8883 l = VectorDistance2(v1, v2);
8884 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8886 l += (1.0f / 1024.0f);
8887 if (shortest[0].length2 > l || i == 0)
8889 shortest[1] = shortest[0];
8890 shortest[0].length2 = l;
8891 shortest[0].v1 = v1;
8892 shortest[0].v2 = v2;
8894 else if (shortest[1].length2 > l || i == 1)
8896 shortest[1].length2 = l;
8897 shortest[1].v1 = v1;
8898 shortest[1].v2 = v2;
8901 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8902 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8903 // this calculates the right vector from the shortest edge
8904 // and the up vector from the edge midpoints
8905 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8906 VectorNormalize(right);
8907 VectorSubtract(end, start, up);
8908 VectorNormalize(up);
8909 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8910 VectorSubtract(rsurface.localvieworigin, center, forward);
8911 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8912 VectorNegate(forward, forward);
8913 VectorReflect(forward, 0, up, forward);
8914 VectorNormalize(forward);
8915 CrossProduct(up, forward, newright);
8916 VectorNormalize(newright);
8917 // rotate the quad around the up axis vector, this is made
8918 // especially easy by the fact we know the quad is flat,
8919 // so we only have to subtract the center position and
8920 // measure distance along the right vector, and then
8921 // multiply that by the newright vector and add back the
8923 // we also need to subtract the old position to undo the
8924 // displacement from the center, which we do with a
8925 // DotProduct, the subtraction/addition of center is also
8926 // optimized into DotProducts here
8927 l = DotProduct(right, center);
8928 for (i = 0;i < 4;i++)
8930 v1 = rsurface.batchvertex3f + 3*(j+i);
8931 f = DotProduct(right, v1) - l;
8932 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8936 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8938 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8939 // rsurface.batchnormal3f_vertexbuffer = NULL;
8940 // rsurface.batchnormal3f_bufferoffset = 0;
8941 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8943 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8945 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8946 // rsurface.batchsvector3f_vertexbuffer = NULL;
8947 // rsurface.batchsvector3f_bufferoffset = 0;
8948 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8949 // rsurface.batchtvector3f_vertexbuffer = NULL;
8950 // rsurface.batchtvector3f_bufferoffset = 0;
8951 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);
8954 case Q3DEFORM_NORMAL:
8955 // deform the normals to make reflections wavey
8956 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8957 rsurface.batchnormal3f_vertexbuffer = NULL;
8958 rsurface.batchnormal3f_bufferoffset = 0;
8959 for (j = 0;j < batchnumvertices;j++)
8962 float *normal = rsurface.batchnormal3f + 3*j;
8963 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8964 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
8965 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
8966 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
8967 VectorNormalize(normal);
8969 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8971 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8972 // rsurface.batchsvector3f_vertexbuffer = NULL;
8973 // rsurface.batchsvector3f_bufferoffset = 0;
8974 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8975 // rsurface.batchtvector3f_vertexbuffer = NULL;
8976 // rsurface.batchtvector3f_bufferoffset = 0;
8977 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);
8981 // deform vertex array to make wavey water and flags and such
8982 waveparms[0] = deform->waveparms[0];
8983 waveparms[1] = deform->waveparms[1];
8984 waveparms[2] = deform->waveparms[2];
8985 waveparms[3] = deform->waveparms[3];
8986 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8987 break; // if wavefunc is a nop, don't make a dynamic vertex array
8988 // this is how a divisor of vertex influence on deformation
8989 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8990 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8991 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8992 // rsurface.batchvertex3f_vertexbuffer = NULL;
8993 // rsurface.batchvertex3f_bufferoffset = 0;
8994 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8995 // rsurface.batchnormal3f_vertexbuffer = NULL;
8996 // rsurface.batchnormal3f_bufferoffset = 0;
8997 for (j = 0;j < batchnumvertices;j++)
8999 // if the wavefunc depends on time, evaluate it per-vertex
9002 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9003 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9005 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9007 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9008 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9009 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9011 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9012 // rsurface.batchsvector3f_vertexbuffer = NULL;
9013 // rsurface.batchsvector3f_bufferoffset = 0;
9014 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9015 // rsurface.batchtvector3f_vertexbuffer = NULL;
9016 // rsurface.batchtvector3f_bufferoffset = 0;
9017 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);
9020 case Q3DEFORM_BULGE:
9021 // deform vertex array to make the surface have moving bulges
9022 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9023 // rsurface.batchvertex3f_vertexbuffer = NULL;
9024 // rsurface.batchvertex3f_bufferoffset = 0;
9025 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9026 // rsurface.batchnormal3f_vertexbuffer = NULL;
9027 // rsurface.batchnormal3f_bufferoffset = 0;
9028 for (j = 0;j < batchnumvertices;j++)
9030 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9031 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9033 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9034 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9035 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9037 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9038 // rsurface.batchsvector3f_vertexbuffer = NULL;
9039 // rsurface.batchsvector3f_bufferoffset = 0;
9040 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9041 // rsurface.batchtvector3f_vertexbuffer = NULL;
9042 // rsurface.batchtvector3f_bufferoffset = 0;
9043 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);
9047 // deform vertex array
9048 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9049 break; // if wavefunc is a nop, don't make a dynamic vertex array
9050 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9051 VectorScale(deform->parms, scale, waveparms);
9052 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9053 // rsurface.batchvertex3f_vertexbuffer = NULL;
9054 // rsurface.batchvertex3f_bufferoffset = 0;
9055 for (j = 0;j < batchnumvertices;j++)
9056 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9061 // generate texcoords based on the chosen texcoord source
9062 switch(rsurface.texture->tcgen.tcgen)
9065 case Q3TCGEN_TEXTURE:
9067 case Q3TCGEN_LIGHTMAP:
9068 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9069 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9070 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9071 if (rsurface.batchtexcoordlightmap2f)
9072 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9074 case Q3TCGEN_VECTOR:
9075 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9076 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9077 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9078 for (j = 0;j < batchnumvertices;j++)
9080 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9081 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9084 case Q3TCGEN_ENVIRONMENT:
9085 // make environment reflections using a spheremap
9086 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9087 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9088 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9089 for (j = 0;j < batchnumvertices;j++)
9091 // identical to Q3A's method, but executed in worldspace so
9092 // carried models can be shiny too
9094 float viewer[3], d, reflected[3], worldreflected[3];
9096 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9097 // VectorNormalize(viewer);
9099 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9101 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9102 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9103 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9104 // note: this is proportinal to viewer, so we can normalize later
9106 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9107 VectorNormalize(worldreflected);
9109 // note: this sphere map only uses world x and z!
9110 // so positive and negative y will LOOK THE SAME.
9111 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9112 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9116 // the only tcmod that needs software vertex processing is turbulent, so
9117 // check for it here and apply the changes if needed
9118 // and we only support that as the first one
9119 // (handling a mixture of turbulent and other tcmods would be problematic
9120 // without punting it entirely to a software path)
9121 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9123 amplitude = rsurface.texture->tcmods[0].parms[1];
9124 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9125 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9126 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9127 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9128 for (j = 0;j < batchnumvertices;j++)
9130 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);
9131 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9135 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9137 // convert the modified arrays to vertex structs
9138 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9139 // rsurface.batchvertexmeshbuffer = NULL;
9140 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9141 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9142 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9143 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9144 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9145 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9146 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9148 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9150 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9151 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9154 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9155 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9156 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9157 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9158 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9159 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9160 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9161 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9162 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9166 void RSurf_DrawBatch(void)
9168 // sometimes a zero triangle surface (usually a degenerate patch) makes it
9169 // through the pipeline, killing it earlier in the pipeline would have
9170 // per-surface overhead rather than per-batch overhead, so it's best to
9171 // reject it here, before it hits glDraw.
9172 if (rsurface.batchnumtriangles == 0)
9175 // batch debugging code
9176 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9182 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9183 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9186 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9188 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9190 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9191 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);
9198 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);
9201 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9203 // pick the closest matching water plane
9204 int planeindex, vertexindex, bestplaneindex = -1;
9208 r_waterstate_waterplane_t *p;
9209 qboolean prepared = false;
9211 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9213 if(p->camera_entity != rsurface.texture->camera_entity)
9218 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9220 if(rsurface.batchnumvertices == 0)
9223 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9225 Matrix4x4_Transform(&rsurface.matrix, v, vert);
9226 d += fabs(PlaneDiff(vert, &p->plane));
9228 if (bestd > d || bestplaneindex < 0)
9231 bestplaneindex = planeindex;
9234 return bestplaneindex;
9235 // NOTE: this MAY return a totally unrelated water plane; we can ignore
9236 // this situation though, as it might be better to render single larger
9237 // batches with useless stuff (backface culled for example) than to
9238 // render multiple smaller batches
9241 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9244 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9245 rsurface.passcolor4f_vertexbuffer = 0;
9246 rsurface.passcolor4f_bufferoffset = 0;
9247 for (i = 0;i < rsurface.batchnumvertices;i++)
9248 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9251 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9258 if (rsurface.passcolor4f)
9260 // generate color arrays
9261 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9262 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9263 rsurface.passcolor4f_vertexbuffer = 0;
9264 rsurface.passcolor4f_bufferoffset = 0;
9265 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)
9267 f = RSurf_FogVertex(v);
9276 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9277 rsurface.passcolor4f_vertexbuffer = 0;
9278 rsurface.passcolor4f_bufferoffset = 0;
9279 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9281 f = RSurf_FogVertex(v);
9290 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9297 if (!rsurface.passcolor4f)
9299 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9300 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9301 rsurface.passcolor4f_vertexbuffer = 0;
9302 rsurface.passcolor4f_bufferoffset = 0;
9303 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)
9305 f = RSurf_FogVertex(v);
9306 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9307 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9308 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9313 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9318 if (!rsurface.passcolor4f)
9320 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9321 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9322 rsurface.passcolor4f_vertexbuffer = 0;
9323 rsurface.passcolor4f_bufferoffset = 0;
9324 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9333 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9338 if (!rsurface.passcolor4f)
9340 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9341 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9342 rsurface.passcolor4f_vertexbuffer = 0;
9343 rsurface.passcolor4f_bufferoffset = 0;
9344 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9346 c2[0] = c[0] + r_refdef.scene.ambient;
9347 c2[1] = c[1] + r_refdef.scene.ambient;
9348 c2[2] = c[2] + r_refdef.scene.ambient;
9353 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9356 rsurface.passcolor4f = NULL;
9357 rsurface.passcolor4f_vertexbuffer = 0;
9358 rsurface.passcolor4f_bufferoffset = 0;
9359 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9360 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9361 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9362 GL_Color(r, g, b, a);
9363 R_Mesh_TexBind(0, rsurface.lightmaptexture);
9367 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9369 // TODO: optimize applyfog && applycolor case
9370 // just apply fog if necessary, and tint the fog color array if necessary
9371 rsurface.passcolor4f = NULL;
9372 rsurface.passcolor4f_vertexbuffer = 0;
9373 rsurface.passcolor4f_bufferoffset = 0;
9374 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9375 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9376 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9377 GL_Color(r, g, b, a);
9381 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9384 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9385 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9386 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9387 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9388 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9389 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9390 GL_Color(r, g, b, a);
9394 static void RSurf_DrawBatch_GL11_ClampColor(void)
9399 if (!rsurface.passcolor4f)
9401 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9403 c2[0] = bound(0.0f, c1[0], 1.0f);
9404 c2[1] = bound(0.0f, c1[1], 1.0f);
9405 c2[2] = bound(0.0f, c1[2], 1.0f);
9406 c2[3] = bound(0.0f, c1[3], 1.0f);
9410 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9420 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9421 rsurface.passcolor4f_vertexbuffer = 0;
9422 rsurface.passcolor4f_bufferoffset = 0;
9423 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)
9425 f = -DotProduct(r_refdef.view.forward, n);
9427 f = f * 0.85 + 0.15; // work around so stuff won't get black
9428 f *= r_refdef.lightmapintensity;
9429 Vector4Set(c, f, f, f, 1);
9433 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9435 RSurf_DrawBatch_GL11_ApplyFakeLight();
9436 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9437 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9438 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9439 GL_Color(r, g, b, a);
9443 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9451 vec3_t ambientcolor;
9452 vec3_t diffusecolor;
9456 VectorCopy(rsurface.modellight_lightdir, lightdir);
9457 f = 0.5f * r_refdef.lightmapintensity;
9458 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9459 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9460 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9461 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9462 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9463 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9465 if (VectorLength2(diffusecolor) > 0)
9467 // q3-style directional shading
9468 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9469 rsurface.passcolor4f_vertexbuffer = 0;
9470 rsurface.passcolor4f_bufferoffset = 0;
9471 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)
9473 if ((f = DotProduct(n, lightdir)) > 0)
9474 VectorMA(ambientcolor, f, diffusecolor, c);
9476 VectorCopy(ambientcolor, c);
9483 *applycolor = false;
9487 *r = ambientcolor[0];
9488 *g = ambientcolor[1];
9489 *b = ambientcolor[2];
9490 rsurface.passcolor4f = NULL;
9491 rsurface.passcolor4f_vertexbuffer = 0;
9492 rsurface.passcolor4f_bufferoffset = 0;
9496 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9498 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9499 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9500 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9501 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9502 GL_Color(r, g, b, a);
9506 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9514 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9515 rsurface.passcolor4f_vertexbuffer = 0;
9516 rsurface.passcolor4f_bufferoffset = 0;
9518 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9520 f = 1 - RSurf_FogVertex(v);
9528 void RSurf_SetupDepthAndCulling(void)
9530 // submodels are biased to avoid z-fighting with world surfaces that they
9531 // may be exactly overlapping (avoids z-fighting artifacts on certain
9532 // doors and things in Quake maps)
9533 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9534 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9535 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9536 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9539 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9541 // transparent sky would be ridiculous
9542 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9544 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
9545 skyrenderlater = true;
9546 RSurf_SetupDepthAndCulling();
9548 // LordHavoc: HalfLife maps have freaky skypolys so don't use
9549 // skymasking on them, and Quake3 never did sky masking (unlike
9550 // software Quake and software Quake2), so disable the sky masking
9551 // in Quake3 maps as it causes problems with q3map2 sky tricks,
9552 // and skymasking also looks very bad when noclipping outside the
9553 // level, so don't use it then either.
9554 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
9556 R_Mesh_ResetTextureState();
9557 if (skyrendermasked)
9559 R_SetupShader_DepthOrShadow(false);
9560 // depth-only (masking)
9561 GL_ColorMask(0,0,0,0);
9562 // just to make sure that braindead drivers don't draw
9563 // anything despite that colormask...
9564 GL_BlendFunc(GL_ZERO, GL_ONE);
9565 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9566 if (rsurface.batchvertex3fbuffer)
9567 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9569 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9573 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
9575 GL_BlendFunc(GL_ONE, GL_ZERO);
9576 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9577 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9578 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9581 if (skyrendermasked)
9582 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9584 R_Mesh_ResetTextureState();
9585 GL_Color(1, 1, 1, 1);
9588 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9589 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9590 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9592 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9596 // render screenspace normalmap to texture
9598 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
9602 // bind lightmap texture
9604 // water/refraction/reflection/camera surfaces have to be handled specially
9605 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9607 int start, end, startplaneindex;
9608 for (start = 0;start < texturenumsurfaces;start = end)
9610 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9611 if(startplaneindex < 0)
9613 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9614 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9618 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9620 // now that we have a batch using the same planeindex, render it
9621 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9623 // render water or distortion background
9625 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), false);
9627 // blend surface on top
9628 GL_DepthMask(false);
9629 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
9632 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9634 // render surface with reflection texture as input
9635 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9636 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), false);
9643 // render surface batch normally
9644 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9645 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) != 0);
9649 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9651 // OpenGL 1.3 path - anything not completely ancient
9652 qboolean applycolor;
9655 const texturelayer_t *layer;
9656 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);
9657 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9659 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9662 int layertexrgbscale;
9663 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9665 if (layerindex == 0)
9669 GL_AlphaTest(false);
9670 GL_DepthFunc(GL_EQUAL);
9673 GL_DepthMask(layer->depthmask && writedepth);
9674 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9675 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9677 layertexrgbscale = 4;
9678 VectorScale(layer->color, 0.25f, layercolor);
9680 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9682 layertexrgbscale = 2;
9683 VectorScale(layer->color, 0.5f, layercolor);
9687 layertexrgbscale = 1;
9688 VectorScale(layer->color, 1.0f, layercolor);
9690 layercolor[3] = layer->color[3];
9691 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9692 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9693 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9694 switch (layer->type)
9696 case TEXTURELAYERTYPE_LITTEXTURE:
9697 // single-pass lightmapped texture with 2x rgbscale
9698 R_Mesh_TexBind(0, r_texture_white);
9699 R_Mesh_TexMatrix(0, NULL);
9700 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9701 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9702 R_Mesh_TexBind(1, layer->texture);
9703 R_Mesh_TexMatrix(1, &layer->texmatrix);
9704 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9705 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9706 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9707 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9708 else if (FAKELIGHT_ENABLED)
9709 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9710 else if (rsurface.uselightmaptexture)
9711 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9713 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9715 case TEXTURELAYERTYPE_TEXTURE:
9716 // singletexture unlit texture with transparency support
9717 R_Mesh_TexBind(0, layer->texture);
9718 R_Mesh_TexMatrix(0, &layer->texmatrix);
9719 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9720 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9721 R_Mesh_TexBind(1, 0);
9722 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9723 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9725 case TEXTURELAYERTYPE_FOG:
9726 // singletexture fogging
9729 R_Mesh_TexBind(0, layer->texture);
9730 R_Mesh_TexMatrix(0, &layer->texmatrix);
9731 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9732 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9736 R_Mesh_TexBind(0, 0);
9737 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9739 R_Mesh_TexBind(1, 0);
9740 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9741 // generate a color array for the fog pass
9742 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9743 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9747 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9750 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9752 GL_DepthFunc(GL_LEQUAL);
9753 GL_AlphaTest(false);
9757 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9759 // OpenGL 1.1 - crusty old voodoo path
9762 const texturelayer_t *layer;
9763 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);
9764 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9766 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9768 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9770 if (layerindex == 0)
9774 GL_AlphaTest(false);
9775 GL_DepthFunc(GL_EQUAL);
9778 GL_DepthMask(layer->depthmask && writedepth);
9779 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9780 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9781 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9782 switch (layer->type)
9784 case TEXTURELAYERTYPE_LITTEXTURE:
9785 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9787 // two-pass lit texture with 2x rgbscale
9788 // first the lightmap pass
9789 R_Mesh_TexBind(0, r_texture_white);
9790 R_Mesh_TexMatrix(0, NULL);
9791 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9792 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9793 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9794 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9795 else if (FAKELIGHT_ENABLED)
9796 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9797 else if (rsurface.uselightmaptexture)
9798 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9800 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9801 // then apply the texture to it
9802 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9803 R_Mesh_TexBind(0, layer->texture);
9804 R_Mesh_TexMatrix(0, &layer->texmatrix);
9805 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9806 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9807 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);
9811 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9812 R_Mesh_TexBind(0, layer->texture);
9813 R_Mesh_TexMatrix(0, &layer->texmatrix);
9814 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9815 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9816 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9817 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);
9819 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);
9822 case TEXTURELAYERTYPE_TEXTURE:
9823 // singletexture unlit texture with transparency support
9824 R_Mesh_TexBind(0, layer->texture);
9825 R_Mesh_TexMatrix(0, &layer->texmatrix);
9826 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9827 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9828 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);
9830 case TEXTURELAYERTYPE_FOG:
9831 // singletexture fogging
9834 R_Mesh_TexBind(0, layer->texture);
9835 R_Mesh_TexMatrix(0, &layer->texmatrix);
9836 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9837 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9841 R_Mesh_TexBind(0, 0);
9842 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9844 // generate a color array for the fog pass
9845 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9846 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9850 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9853 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9855 GL_DepthFunc(GL_LEQUAL);
9856 GL_AlphaTest(false);
9860 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9864 r_vertexgeneric_t *batchvertex;
9867 // R_Mesh_ResetTextureState();
9868 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
9870 if(rsurface.texture && rsurface.texture->currentskinframe)
9872 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9873 c[3] *= rsurface.texture->currentalpha;
9883 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9885 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9886 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9887 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9890 // brighten it up (as texture value 127 means "unlit")
9891 c[0] *= 2 * r_refdef.view.colorscale;
9892 c[1] *= 2 * r_refdef.view.colorscale;
9893 c[2] *= 2 * r_refdef.view.colorscale;
9895 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9896 c[3] *= r_wateralpha.value;
9898 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9900 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9901 GL_DepthMask(false);
9903 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9905 GL_BlendFunc(GL_ONE, GL_ONE);
9906 GL_DepthMask(false);
9908 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9910 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9911 GL_DepthMask(false);
9913 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9915 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9916 GL_DepthMask(false);
9920 GL_BlendFunc(GL_ONE, GL_ZERO);
9921 GL_DepthMask(writedepth);
9924 if (r_showsurfaces.integer == 3)
9926 rsurface.passcolor4f = NULL;
9928 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9930 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9932 rsurface.passcolor4f = NULL;
9933 rsurface.passcolor4f_vertexbuffer = 0;
9934 rsurface.passcolor4f_bufferoffset = 0;
9936 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9938 qboolean applycolor = true;
9941 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9943 r_refdef.lightmapintensity = 1;
9944 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9945 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9947 else if (FAKELIGHT_ENABLED)
9949 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9951 r_refdef.lightmapintensity = r_fakelight_intensity.value;
9952 RSurf_DrawBatch_GL11_ApplyFakeLight();
9953 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9957 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9959 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9960 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9961 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9964 if(!rsurface.passcolor4f)
9965 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9967 RSurf_DrawBatch_GL11_ApplyAmbient();
9968 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9969 if(r_refdef.fogenabled)
9970 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9971 RSurf_DrawBatch_GL11_ClampColor();
9973 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9974 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
9977 else if (!r_refdef.view.showdebug)
9979 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9980 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9981 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9983 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9984 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9986 R_Mesh_PrepareVertices_Generic_Unlock();
9989 else if (r_showsurfaces.integer == 4)
9991 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9992 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9993 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9995 unsigned char c = (vi << 3) * (1.0f / 256.0f);
9996 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9997 Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9999 R_Mesh_PrepareVertices_Generic_Unlock();
10002 else if (r_showsurfaces.integer == 2)
10005 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10006 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10007 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10009 unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10010 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10011 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10012 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10013 Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10014 Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10015 Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10017 R_Mesh_PrepareVertices_Generic_Unlock();
10018 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10022 int texturesurfaceindex;
10024 const msurface_t *surface;
10025 float surfacecolor4f[4];
10026 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10027 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10029 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10031 surface = texturesurfacelist[texturesurfaceindex];
10032 k = (int)(((size_t)surface) / sizeof(msurface_t));
10033 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10034 for (j = 0;j < surface->num_vertices;j++)
10036 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10037 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10041 R_Mesh_PrepareVertices_Generic_Unlock();
10046 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10049 RSurf_SetupDepthAndCulling();
10050 if (r_showsurfaces.integer)
10052 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10055 switch (vid.renderpath)
10057 case RENDERPATH_GL20:
10058 case RENDERPATH_D3D9:
10059 case RENDERPATH_D3D10:
10060 case RENDERPATH_D3D11:
10061 case RENDERPATH_SOFT:
10062 case RENDERPATH_GLES2:
10063 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10065 case RENDERPATH_GL13:
10066 case RENDERPATH_GLES1:
10067 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10069 case RENDERPATH_GL11:
10070 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10076 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10079 RSurf_SetupDepthAndCulling();
10080 if (r_showsurfaces.integer)
10082 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10085 switch (vid.renderpath)
10087 case RENDERPATH_GL20:
10088 case RENDERPATH_D3D9:
10089 case RENDERPATH_D3D10:
10090 case RENDERPATH_D3D11:
10091 case RENDERPATH_SOFT:
10092 case RENDERPATH_GLES2:
10093 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10095 case RENDERPATH_GL13:
10096 case RENDERPATH_GLES1:
10097 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10099 case RENDERPATH_GL11:
10100 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10106 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10109 int texturenumsurfaces, endsurface;
10110 texture_t *texture;
10111 const msurface_t *surface;
10112 const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10114 // if the model is static it doesn't matter what value we give for
10115 // wantnormals and wanttangents, so this logic uses only rules applicable
10116 // to a model, knowing that they are meaningless otherwise
10117 if (ent == r_refdef.scene.worldentity)
10118 RSurf_ActiveWorldEntity();
10119 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10120 RSurf_ActiveModelEntity(ent, false, false, false);
10123 switch (vid.renderpath)
10125 case RENDERPATH_GL20:
10126 case RENDERPATH_D3D9:
10127 case RENDERPATH_D3D10:
10128 case RENDERPATH_D3D11:
10129 case RENDERPATH_SOFT:
10130 case RENDERPATH_GLES2:
10131 RSurf_ActiveModelEntity(ent, true, true, false);
10133 case RENDERPATH_GL11:
10134 case RENDERPATH_GL13:
10135 case RENDERPATH_GLES1:
10136 RSurf_ActiveModelEntity(ent, true, false, false);
10141 if (r_transparentdepthmasking.integer)
10143 qboolean setup = false;
10144 for (i = 0;i < numsurfaces;i = j)
10147 surface = rsurface.modelsurfaces + surfacelist[i];
10148 texture = surface->texture;
10149 rsurface.texture = R_GetCurrentTexture(texture);
10150 rsurface.lightmaptexture = NULL;
10151 rsurface.deluxemaptexture = NULL;
10152 rsurface.uselightmaptexture = false;
10153 // scan ahead until we find a different texture
10154 endsurface = min(i + 1024, numsurfaces);
10155 texturenumsurfaces = 0;
10156 texturesurfacelist[texturenumsurfaces++] = surface;
10157 for (;j < endsurface;j++)
10159 surface = rsurface.modelsurfaces + surfacelist[j];
10160 if (texture != surface->texture)
10162 texturesurfacelist[texturenumsurfaces++] = surface;
10164 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10166 // render the range of surfaces as depth
10170 GL_ColorMask(0,0,0,0);
10172 GL_DepthTest(true);
10173 GL_BlendFunc(GL_ONE, GL_ZERO);
10174 GL_DepthMask(true);
10175 // R_Mesh_ResetTextureState();
10176 R_SetupShader_DepthOrShadow(false);
10178 RSurf_SetupDepthAndCulling();
10179 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10180 if (rsurface.batchvertex3fbuffer)
10181 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10183 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10187 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10190 for (i = 0;i < numsurfaces;i = j)
10193 surface = rsurface.modelsurfaces + surfacelist[i];
10194 texture = surface->texture;
10195 rsurface.texture = R_GetCurrentTexture(texture);
10196 // scan ahead until we find a different texture
10197 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10198 texturenumsurfaces = 0;
10199 texturesurfacelist[texturenumsurfaces++] = surface;
10200 if(FAKELIGHT_ENABLED)
10202 rsurface.lightmaptexture = NULL;
10203 rsurface.deluxemaptexture = NULL;
10204 rsurface.uselightmaptexture = false;
10205 for (;j < endsurface;j++)
10207 surface = rsurface.modelsurfaces + surfacelist[j];
10208 if (texture != surface->texture)
10210 texturesurfacelist[texturenumsurfaces++] = surface;
10215 rsurface.lightmaptexture = surface->lightmaptexture;
10216 rsurface.deluxemaptexture = surface->deluxemaptexture;
10217 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10218 for (;j < endsurface;j++)
10220 surface = rsurface.modelsurfaces + surfacelist[j];
10221 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10223 texturesurfacelist[texturenumsurfaces++] = surface;
10226 // render the range of surfaces
10227 if (ent == r_refdef.scene.worldentity)
10228 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10230 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10232 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10235 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10237 // transparent surfaces get pushed off into the transparent queue
10238 int surfacelistindex;
10239 const msurface_t *surface;
10240 vec3_t tempcenter, center;
10241 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10243 surface = texturesurfacelist[surfacelistindex];
10244 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10245 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10246 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10247 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10248 if (queueentity->transparent_offset) // transparent offset
10250 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10251 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10252 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10254 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10258 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10260 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10262 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10264 RSurf_SetupDepthAndCulling();
10265 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10266 if (rsurface.batchvertex3fbuffer)
10267 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10269 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10273 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10275 const entity_render_t *queueentity = r_refdef.scene.worldentity;
10278 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10281 if (!rsurface.texture->currentnumlayers)
10283 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10284 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10286 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10288 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10289 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10290 else if (!rsurface.texture->currentnumlayers)
10292 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10294 // in the deferred case, transparent surfaces were queued during prepass
10295 if (!r_shadow_usingdeferredprepass)
10296 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10300 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10301 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10306 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10309 texture_t *texture;
10310 R_FrameData_SetMark();
10311 // break the surface list down into batches by texture and use of lightmapping
10312 for (i = 0;i < numsurfaces;i = j)
10315 // texture is the base texture pointer, rsurface.texture is the
10316 // current frame/skin the texture is directing us to use (for example
10317 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10318 // use skin 1 instead)
10319 texture = surfacelist[i]->texture;
10320 rsurface.texture = R_GetCurrentTexture(texture);
10321 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10323 // if this texture is not the kind we want, skip ahead to the next one
10324 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10328 if(FAKELIGHT_ENABLED || depthonly || prepass)
10330 rsurface.lightmaptexture = NULL;
10331 rsurface.deluxemaptexture = NULL;
10332 rsurface.uselightmaptexture = false;
10333 // simply scan ahead until we find a different texture or lightmap state
10334 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10339 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10340 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10341 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10342 // simply scan ahead until we find a different texture or lightmap state
10343 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10346 // render the range of surfaces
10347 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10349 R_FrameData_ReturnToMark();
10352 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10356 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10359 if (!rsurface.texture->currentnumlayers)
10361 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10362 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10364 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10366 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10367 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10368 else if (!rsurface.texture->currentnumlayers)
10370 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10372 // in the deferred case, transparent surfaces were queued during prepass
10373 if (!r_shadow_usingdeferredprepass)
10374 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10378 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10379 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10384 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10387 texture_t *texture;
10388 R_FrameData_SetMark();
10389 // break the surface list down into batches by texture and use of lightmapping
10390 for (i = 0;i < numsurfaces;i = j)
10393 // texture is the base texture pointer, rsurface.texture is the
10394 // current frame/skin the texture is directing us to use (for example
10395 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10396 // use skin 1 instead)
10397 texture = surfacelist[i]->texture;
10398 rsurface.texture = R_GetCurrentTexture(texture);
10399 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10401 // if this texture is not the kind we want, skip ahead to the next one
10402 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10406 if(FAKELIGHT_ENABLED || depthonly || prepass)
10408 rsurface.lightmaptexture = NULL;
10409 rsurface.deluxemaptexture = NULL;
10410 rsurface.uselightmaptexture = false;
10411 // simply scan ahead until we find a different texture or lightmap state
10412 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10417 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10418 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10419 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10420 // simply scan ahead until we find a different texture or lightmap state
10421 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10424 // render the range of surfaces
10425 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10427 R_FrameData_ReturnToMark();
10430 float locboxvertex3f[6*4*3] =
10432 1,0,1, 1,0,0, 1,1,0, 1,1,1,
10433 0,1,1, 0,1,0, 0,0,0, 0,0,1,
10434 1,1,1, 1,1,0, 0,1,0, 0,1,1,
10435 0,0,1, 0,0,0, 1,0,0, 1,0,1,
10436 0,0,1, 1,0,1, 1,1,1, 0,1,1,
10437 1,0,0, 0,0,0, 0,1,0, 1,1,0
10440 unsigned short locboxelements[6*2*3] =
10445 12,13,14, 12,14,15,
10446 16,17,18, 16,18,19,
10450 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10453 cl_locnode_t *loc = (cl_locnode_t *)ent;
10455 float vertex3f[6*4*3];
10457 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10458 GL_DepthMask(false);
10459 GL_DepthRange(0, 1);
10460 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10461 GL_DepthTest(true);
10462 GL_CullFace(GL_NONE);
10463 R_EntityMatrix(&identitymatrix);
10465 // R_Mesh_ResetTextureState();
10467 i = surfacelist[0];
10468 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10469 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10470 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10471 surfacelist[0] < 0 ? 0.5f : 0.125f);
10473 if (VectorCompare(loc->mins, loc->maxs))
10475 VectorSet(size, 2, 2, 2);
10476 VectorMA(loc->mins, -0.5f, size, mins);
10480 VectorCopy(loc->mins, mins);
10481 VectorSubtract(loc->maxs, loc->mins, size);
10484 for (i = 0;i < 6*4*3;)
10485 for (j = 0;j < 3;j++, i++)
10486 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10488 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10489 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
10490 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10493 void R_DrawLocs(void)
10496 cl_locnode_t *loc, *nearestloc;
10498 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10499 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10501 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10502 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10506 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10508 if (decalsystem->decals)
10509 Mem_Free(decalsystem->decals);
10510 memset(decalsystem, 0, sizeof(*decalsystem));
10513 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)
10516 tridecal_t *decals;
10519 // expand or initialize the system
10520 if (decalsystem->maxdecals <= decalsystem->numdecals)
10522 decalsystem_t old = *decalsystem;
10523 qboolean useshortelements;
10524 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10525 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10526 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)));
10527 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10528 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10529 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10530 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10531 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10532 if (decalsystem->numdecals)
10533 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10535 Mem_Free(old.decals);
10536 for (i = 0;i < decalsystem->maxdecals*3;i++)
10537 decalsystem->element3i[i] = i;
10538 if (useshortelements)
10539 for (i = 0;i < decalsystem->maxdecals*3;i++)
10540 decalsystem->element3s[i] = i;
10543 // grab a decal and search for another free slot for the next one
10544 decals = decalsystem->decals;
10545 decal = decalsystem->decals + (i = decalsystem->freedecal++);
10546 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10548 decalsystem->freedecal = i;
10549 if (decalsystem->numdecals <= i)
10550 decalsystem->numdecals = i + 1;
10552 // initialize the decal
10554 decal->triangleindex = triangleindex;
10555 decal->surfaceindex = surfaceindex;
10556 decal->decalsequence = decalsequence;
10557 decal->color4f[0][0] = c0[0];
10558 decal->color4f[0][1] = c0[1];
10559 decal->color4f[0][2] = c0[2];
10560 decal->color4f[0][3] = 1;
10561 decal->color4f[1][0] = c1[0];
10562 decal->color4f[1][1] = c1[1];
10563 decal->color4f[1][2] = c1[2];
10564 decal->color4f[1][3] = 1;
10565 decal->color4f[2][0] = c2[0];
10566 decal->color4f[2][1] = c2[1];
10567 decal->color4f[2][2] = c2[2];
10568 decal->color4f[2][3] = 1;
10569 decal->vertex3f[0][0] = v0[0];
10570 decal->vertex3f[0][1] = v0[1];
10571 decal->vertex3f[0][2] = v0[2];
10572 decal->vertex3f[1][0] = v1[0];
10573 decal->vertex3f[1][1] = v1[1];
10574 decal->vertex3f[1][2] = v1[2];
10575 decal->vertex3f[2][0] = v2[0];
10576 decal->vertex3f[2][1] = v2[1];
10577 decal->vertex3f[2][2] = v2[2];
10578 decal->texcoord2f[0][0] = t0[0];
10579 decal->texcoord2f[0][1] = t0[1];
10580 decal->texcoord2f[1][0] = t1[0];
10581 decal->texcoord2f[1][1] = t1[1];
10582 decal->texcoord2f[2][0] = t2[0];
10583 decal->texcoord2f[2][1] = t2[1];
10584 TriangleNormal(v0, v1, v2, decal->plane);
10585 VectorNormalize(decal->plane);
10586 decal->plane[3] = DotProduct(v0, decal->plane);
10589 extern cvar_t cl_decals_bias;
10590 extern cvar_t cl_decals_models;
10591 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10592 // baseparms, parms, temps
10593 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)
10598 const float *vertex3f;
10599 const float *normal3f;
10601 float points[2][9][3];
10608 e = rsurface.modelelement3i + 3*triangleindex;
10610 vertex3f = rsurface.modelvertex3f;
10611 normal3f = rsurface.modelnormal3f;
10615 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10617 index = 3*e[cornerindex];
10618 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10623 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10625 index = 3*e[cornerindex];
10626 VectorCopy(vertex3f + index, v[cornerindex]);
10631 //TriangleNormal(v[0], v[1], v[2], normal);
10632 //if (DotProduct(normal, localnormal) < 0.0f)
10634 // clip by each of the box planes formed from the projection matrix
10635 // if anything survives, we emit the decal
10636 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]);
10639 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]);
10642 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]);
10645 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]);
10648 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]);
10651 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]);
10654 // some part of the triangle survived, so we have to accept it...
10657 // dynamic always uses the original triangle
10659 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10661 index = 3*e[cornerindex];
10662 VectorCopy(vertex3f + index, v[cornerindex]);
10665 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10667 // convert vertex positions to texcoords
10668 Matrix4x4_Transform(projection, v[cornerindex], temp);
10669 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10670 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10671 // calculate distance fade from the projection origin
10672 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10673 f = bound(0.0f, f, 1.0f);
10674 c[cornerindex][0] = r * f;
10675 c[cornerindex][1] = g * f;
10676 c[cornerindex][2] = b * f;
10677 c[cornerindex][3] = 1.0f;
10678 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10681 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);
10683 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10684 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);
10686 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)
10688 matrix4x4_t projection;
10689 decalsystem_t *decalsystem;
10692 const msurface_t *surface;
10693 const msurface_t *surfaces;
10694 const int *surfacelist;
10695 const texture_t *texture;
10697 int numsurfacelist;
10698 int surfacelistindex;
10701 float localorigin[3];
10702 float localnormal[3];
10703 float localmins[3];
10704 float localmaxs[3];
10707 float planes[6][4];
10710 int bih_triangles_count;
10711 int bih_triangles[256];
10712 int bih_surfaces[256];
10714 decalsystem = &ent->decalsystem;
10715 model = ent->model;
10716 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10718 R_DecalSystem_Reset(&ent->decalsystem);
10722 if (!model->brush.data_leafs && !cl_decals_models.integer)
10724 if (decalsystem->model)
10725 R_DecalSystem_Reset(decalsystem);
10729 if (decalsystem->model != model)
10730 R_DecalSystem_Reset(decalsystem);
10731 decalsystem->model = model;
10733 RSurf_ActiveModelEntity(ent, true, false, false);
10735 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10736 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10737 VectorNormalize(localnormal);
10738 localsize = worldsize*rsurface.inversematrixscale;
10739 localmins[0] = localorigin[0] - localsize;
10740 localmins[1] = localorigin[1] - localsize;
10741 localmins[2] = localorigin[2] - localsize;
10742 localmaxs[0] = localorigin[0] + localsize;
10743 localmaxs[1] = localorigin[1] + localsize;
10744 localmaxs[2] = localorigin[2] + localsize;
10746 //VectorCopy(localnormal, planes[4]);
10747 //VectorVectors(planes[4], planes[2], planes[0]);
10748 AnglesFromVectors(angles, localnormal, NULL, false);
10749 AngleVectors(angles, planes[0], planes[2], planes[4]);
10750 VectorNegate(planes[0], planes[1]);
10751 VectorNegate(planes[2], planes[3]);
10752 VectorNegate(planes[4], planes[5]);
10753 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10754 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10755 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10756 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10757 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10758 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10763 matrix4x4_t forwardprojection;
10764 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10765 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10770 float projectionvector[4][3];
10771 VectorScale(planes[0], ilocalsize, projectionvector[0]);
10772 VectorScale(planes[2], ilocalsize, projectionvector[1]);
10773 VectorScale(planes[4], ilocalsize, projectionvector[2]);
10774 projectionvector[0][0] = planes[0][0] * ilocalsize;
10775 projectionvector[0][1] = planes[1][0] * ilocalsize;
10776 projectionvector[0][2] = planes[2][0] * ilocalsize;
10777 projectionvector[1][0] = planes[0][1] * ilocalsize;
10778 projectionvector[1][1] = planes[1][1] * ilocalsize;
10779 projectionvector[1][2] = planes[2][1] * ilocalsize;
10780 projectionvector[2][0] = planes[0][2] * ilocalsize;
10781 projectionvector[2][1] = planes[1][2] * ilocalsize;
10782 projectionvector[2][2] = planes[2][2] * ilocalsize;
10783 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10784 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10785 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10786 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10790 dynamic = model->surfmesh.isanimated;
10791 numsurfacelist = model->nummodelsurfaces;
10792 surfacelist = model->sortedmodelsurfaces;
10793 surfaces = model->data_surfaces;
10796 bih_triangles_count = -1;
10799 if(model->render_bih.numleafs)
10800 bih = &model->render_bih;
10801 else if(model->collision_bih.numleafs)
10802 bih = &model->collision_bih;
10805 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10806 if(bih_triangles_count == 0)
10808 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10810 if(bih_triangles_count > 0)
10812 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10814 surfaceindex = bih_surfaces[triangleindex];
10815 surface = surfaces + surfaceindex;
10816 texture = surface->texture;
10817 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10819 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10821 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10826 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10828 surfaceindex = surfacelist[surfacelistindex];
10829 surface = surfaces + surfaceindex;
10830 // check cull box first because it rejects more than any other check
10831 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10833 // skip transparent surfaces
10834 texture = surface->texture;
10835 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10837 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10839 numtriangles = surface->num_triangles;
10840 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10841 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10846 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10847 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)
10849 int renderentityindex;
10850 float worldmins[3];
10851 float worldmaxs[3];
10852 entity_render_t *ent;
10854 if (!cl_decals_newsystem.integer)
10857 worldmins[0] = worldorigin[0] - worldsize;
10858 worldmins[1] = worldorigin[1] - worldsize;
10859 worldmins[2] = worldorigin[2] - worldsize;
10860 worldmaxs[0] = worldorigin[0] + worldsize;
10861 worldmaxs[1] = worldorigin[1] + worldsize;
10862 worldmaxs[2] = worldorigin[2] + worldsize;
10864 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10866 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10868 ent = r_refdef.scene.entities[renderentityindex];
10869 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10872 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10876 typedef struct r_decalsystem_splatqueue_s
10878 vec3_t worldorigin;
10879 vec3_t worldnormal;
10885 r_decalsystem_splatqueue_t;
10887 int r_decalsystem_numqueued = 0;
10888 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10890 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)
10892 r_decalsystem_splatqueue_t *queue;
10894 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10897 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10898 VectorCopy(worldorigin, queue->worldorigin);
10899 VectorCopy(worldnormal, queue->worldnormal);
10900 Vector4Set(queue->color, r, g, b, a);
10901 Vector4Set(queue->tcrange, s1, t1, s2, t2);
10902 queue->worldsize = worldsize;
10903 queue->decalsequence = cl.decalsequence++;
10906 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10909 r_decalsystem_splatqueue_t *queue;
10911 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10912 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);
10913 r_decalsystem_numqueued = 0;
10916 extern cvar_t cl_decals_max;
10917 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10920 decalsystem_t *decalsystem = &ent->decalsystem;
10927 if (!decalsystem->numdecals)
10930 if (r_showsurfaces.integer)
10933 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10935 R_DecalSystem_Reset(decalsystem);
10939 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10940 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10942 if (decalsystem->lastupdatetime)
10943 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
10946 decalsystem->lastupdatetime = r_refdef.scene.time;
10947 decal = decalsystem->decals;
10948 numdecals = decalsystem->numdecals;
10950 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10952 if (decal->color4f[0][3])
10954 decal->lived += frametime;
10955 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10957 memset(decal, 0, sizeof(*decal));
10958 if (decalsystem->freedecal > i)
10959 decalsystem->freedecal = i;
10963 decal = decalsystem->decals;
10964 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10967 // collapse the array by shuffling the tail decals into the gaps
10970 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10971 decalsystem->freedecal++;
10972 if (decalsystem->freedecal == numdecals)
10974 decal[decalsystem->freedecal] = decal[--numdecals];
10977 decalsystem->numdecals = numdecals;
10979 if (numdecals <= 0)
10981 // if there are no decals left, reset decalsystem
10982 R_DecalSystem_Reset(decalsystem);
10986 extern skinframe_t *decalskinframe;
10987 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10990 decalsystem_t *decalsystem = &ent->decalsystem;
10999 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11002 numdecals = decalsystem->numdecals;
11006 if (r_showsurfaces.integer)
11009 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11011 R_DecalSystem_Reset(decalsystem);
11015 // if the model is static it doesn't matter what value we give for
11016 // wantnormals and wanttangents, so this logic uses only rules applicable
11017 // to a model, knowing that they are meaningless otherwise
11018 if (ent == r_refdef.scene.worldentity)
11019 RSurf_ActiveWorldEntity();
11021 RSurf_ActiveModelEntity(ent, false, false, false);
11023 decalsystem->lastupdatetime = r_refdef.scene.time;
11024 decal = decalsystem->decals;
11026 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11028 // update vertex positions for animated models
11029 v3f = decalsystem->vertex3f;
11030 c4f = decalsystem->color4f;
11031 t2f = decalsystem->texcoord2f;
11032 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11034 if (!decal->color4f[0][3])
11037 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11041 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11044 // update color values for fading decals
11045 if (decal->lived >= cl_decals_time.value)
11046 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11050 c4f[ 0] = decal->color4f[0][0] * alpha;
11051 c4f[ 1] = decal->color4f[0][1] * alpha;
11052 c4f[ 2] = decal->color4f[0][2] * alpha;
11054 c4f[ 4] = decal->color4f[1][0] * alpha;
11055 c4f[ 5] = decal->color4f[1][1] * alpha;
11056 c4f[ 6] = decal->color4f[1][2] * alpha;
11058 c4f[ 8] = decal->color4f[2][0] * alpha;
11059 c4f[ 9] = decal->color4f[2][1] * alpha;
11060 c4f[10] = decal->color4f[2][2] * alpha;
11063 t2f[0] = decal->texcoord2f[0][0];
11064 t2f[1] = decal->texcoord2f[0][1];
11065 t2f[2] = decal->texcoord2f[1][0];
11066 t2f[3] = decal->texcoord2f[1][1];
11067 t2f[4] = decal->texcoord2f[2][0];
11068 t2f[5] = decal->texcoord2f[2][1];
11070 // update vertex positions for animated models
11071 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11073 e = rsurface.modelelement3i + 3*decal->triangleindex;
11074 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11075 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11076 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11080 VectorCopy(decal->vertex3f[0], v3f);
11081 VectorCopy(decal->vertex3f[1], v3f + 3);
11082 VectorCopy(decal->vertex3f[2], v3f + 6);
11085 if (r_refdef.fogenabled)
11087 alpha = RSurf_FogVertex(v3f);
11088 VectorScale(c4f, alpha, c4f);
11089 alpha = RSurf_FogVertex(v3f + 3);
11090 VectorScale(c4f + 4, alpha, c4f + 4);
11091 alpha = RSurf_FogVertex(v3f + 6);
11092 VectorScale(c4f + 8, alpha, c4f + 8);
11103 r_refdef.stats.drawndecals += numtris;
11105 // now render the decals all at once
11106 // (this assumes they all use one particle font texture!)
11107 RSurf_ActiveCustomEntity(&rsurface.matrix, &rsurface.inversematrix, rsurface.ent_flags, ent->shadertime, 1, 1, 1, 1, numdecals*3, decalsystem->vertex3f, decalsystem->texcoord2f, NULL, NULL, NULL, decalsystem->color4f, numtris, decalsystem->element3i, decalsystem->element3s, false, false);
11108 // R_Mesh_ResetTextureState();
11109 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11110 GL_DepthMask(false);
11111 GL_DepthRange(0, 1);
11112 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11113 GL_DepthTest(true);
11114 GL_CullFace(GL_NONE);
11115 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11116 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false);
11117 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11121 static void R_DrawModelDecals(void)
11125 // fade faster when there are too many decals
11126 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11127 for (i = 0;i < r_refdef.scene.numentities;i++)
11128 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11130 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11131 for (i = 0;i < r_refdef.scene.numentities;i++)
11132 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11133 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11135 R_DecalSystem_ApplySplatEntitiesQueue();
11137 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11138 for (i = 0;i < r_refdef.scene.numentities;i++)
11139 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11141 r_refdef.stats.totaldecals += numdecals;
11143 if (r_showsurfaces.integer)
11146 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11148 for (i = 0;i < r_refdef.scene.numentities;i++)
11150 if (!r_refdef.viewcache.entityvisible[i])
11152 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11153 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11157 extern cvar_t mod_collision_bih;
11158 void R_DrawDebugModel(void)
11160 entity_render_t *ent = rsurface.entity;
11161 int i, j, k, l, flagsmask;
11162 const msurface_t *surface;
11163 dp_model_t *model = ent->model;
11166 if (!sv.active && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11169 if (r_showoverdraw.value > 0)
11171 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11172 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11173 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
11174 GL_DepthTest(false);
11175 GL_DepthMask(false);
11176 GL_DepthRange(0, 1);
11177 GL_BlendFunc(GL_ONE, GL_ONE);
11178 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11180 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11182 rsurface.texture = R_GetCurrentTexture(surface->texture);
11183 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11185 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11186 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11187 if (!rsurface.texture->currentlayers->depthmask)
11188 GL_Color(c, 0, 0, 1.0f);
11189 else if (ent == r_refdef.scene.worldentity)
11190 GL_Color(c, c, c, 1.0f);
11192 GL_Color(0, c, 0, 1.0f);
11193 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11197 rsurface.texture = NULL;
11200 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11202 // R_Mesh_ResetTextureState();
11203 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
11204 GL_DepthRange(0, 1);
11205 GL_DepthTest(!r_showdisabledepthtest.integer);
11206 GL_DepthMask(false);
11207 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11209 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11213 qboolean cullbox = ent == r_refdef.scene.worldentity;
11214 const q3mbrush_t *brush;
11215 const bih_t *bih = &model->collision_bih;
11216 const bih_leaf_t *bihleaf;
11217 float vertex3f[3][3];
11218 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11220 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11222 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11224 switch (bihleaf->type)
11227 brush = model->brush.data_brushes + bihleaf->itemindex;
11228 if (brush->colbrushf && brush->colbrushf->numtriangles)
11230 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);
11231 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11232 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11235 case BIH_COLLISIONTRIANGLE:
11236 triangleindex = bihleaf->itemindex;
11237 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11238 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11239 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11240 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);
11241 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11242 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11244 case BIH_RENDERTRIANGLE:
11245 triangleindex = bihleaf->itemindex;
11246 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11247 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11248 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11249 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);
11250 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11251 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11257 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11259 if (r_showtris.integer && qglPolygonMode)
11261 if (r_showdisabledepthtest.integer)
11263 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11264 GL_DepthMask(false);
11268 GL_BlendFunc(GL_ONE, GL_ZERO);
11269 GL_DepthMask(true);
11271 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11272 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11274 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11276 rsurface.texture = R_GetCurrentTexture(surface->texture);
11277 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11279 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11280 if (!rsurface.texture->currentlayers->depthmask)
11281 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11282 else if (ent == r_refdef.scene.worldentity)
11283 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11285 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11286 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11290 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11291 rsurface.texture = NULL;
11294 if (r_shownormals.value != 0 && qglBegin)
11296 if (r_showdisabledepthtest.integer)
11298 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11299 GL_DepthMask(false);
11303 GL_BlendFunc(GL_ONE, GL_ZERO);
11304 GL_DepthMask(true);
11306 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11308 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11310 rsurface.texture = R_GetCurrentTexture(surface->texture);
11311 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11313 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11314 qglBegin(GL_LINES);
11315 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11317 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11319 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11320 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11321 qglVertex3f(v[0], v[1], v[2]);
11322 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11323 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11324 qglVertex3f(v[0], v[1], v[2]);
11327 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11329 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11331 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11332 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11333 qglVertex3f(v[0], v[1], v[2]);
11334 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11335 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11336 qglVertex3f(v[0], v[1], v[2]);
11339 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11341 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11343 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11344 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11345 qglVertex3f(v[0], v[1], v[2]);
11346 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11347 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11348 qglVertex3f(v[0], v[1], v[2]);
11351 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11353 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11355 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11356 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11357 qglVertex3f(v[0], v[1], v[2]);
11358 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11359 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11360 qglVertex3f(v[0], v[1], v[2]);
11367 rsurface.texture = NULL;
11371 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11372 int r_maxsurfacelist = 0;
11373 const msurface_t **r_surfacelist = NULL;
11374 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11376 int i, j, endj, flagsmask;
11377 dp_model_t *model = r_refdef.scene.worldmodel;
11378 msurface_t *surfaces;
11379 unsigned char *update;
11380 int numsurfacelist = 0;
11384 if (r_maxsurfacelist < model->num_surfaces)
11386 r_maxsurfacelist = model->num_surfaces;
11388 Mem_Free((msurface_t**)r_surfacelist);
11389 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11392 RSurf_ActiveWorldEntity();
11394 surfaces = model->data_surfaces;
11395 update = model->brushq1.lightmapupdateflags;
11397 // update light styles on this submodel
11398 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11400 model_brush_lightstyleinfo_t *style;
11401 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11403 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11405 int *list = style->surfacelist;
11406 style->value = r_refdef.scene.lightstylevalue[style->style];
11407 for (j = 0;j < style->numsurfaces;j++)
11408 update[list[j]] = true;
11413 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11417 R_DrawDebugModel();
11418 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11422 rsurface.lightmaptexture = NULL;
11423 rsurface.deluxemaptexture = NULL;
11424 rsurface.uselightmaptexture = false;
11425 rsurface.texture = NULL;
11426 rsurface.rtlight = NULL;
11427 numsurfacelist = 0;
11428 // add visible surfaces to draw list
11429 for (i = 0;i < model->nummodelsurfaces;i++)
11431 j = model->sortedmodelsurfaces[i];
11432 if (r_refdef.viewcache.world_surfacevisible[j])
11433 r_surfacelist[numsurfacelist++] = surfaces + j;
11435 // update lightmaps if needed
11436 if (model->brushq1.firstrender)
11438 model->brushq1.firstrender = false;
11439 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11441 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11445 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11446 if (r_refdef.viewcache.world_surfacevisible[j])
11448 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11450 // don't do anything if there were no surfaces
11451 if (!numsurfacelist)
11453 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11456 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11458 // add to stats if desired
11459 if (r_speeds.integer && !skysurfaces && !depthonly)
11461 r_refdef.stats.world_surfaces += numsurfacelist;
11462 for (j = 0;j < numsurfacelist;j++)
11463 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11466 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11469 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11471 int i, j, endj, flagsmask;
11472 dp_model_t *model = ent->model;
11473 msurface_t *surfaces;
11474 unsigned char *update;
11475 int numsurfacelist = 0;
11479 if (r_maxsurfacelist < model->num_surfaces)
11481 r_maxsurfacelist = model->num_surfaces;
11483 Mem_Free((msurface_t **)r_surfacelist);
11484 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11487 // if the model is static it doesn't matter what value we give for
11488 // wantnormals and wanttangents, so this logic uses only rules applicable
11489 // to a model, knowing that they are meaningless otherwise
11490 if (ent == r_refdef.scene.worldentity)
11491 RSurf_ActiveWorldEntity();
11492 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11493 RSurf_ActiveModelEntity(ent, false, false, false);
11495 RSurf_ActiveModelEntity(ent, true, true, true);
11496 else if (depthonly)
11498 switch (vid.renderpath)
11500 case RENDERPATH_GL20:
11501 case RENDERPATH_D3D9:
11502 case RENDERPATH_D3D10:
11503 case RENDERPATH_D3D11:
11504 case RENDERPATH_SOFT:
11505 case RENDERPATH_GLES2:
11506 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11508 case RENDERPATH_GL11:
11509 case RENDERPATH_GL13:
11510 case RENDERPATH_GLES1:
11511 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11517 switch (vid.renderpath)
11519 case RENDERPATH_GL20:
11520 case RENDERPATH_D3D9:
11521 case RENDERPATH_D3D10:
11522 case RENDERPATH_D3D11:
11523 case RENDERPATH_SOFT:
11524 case RENDERPATH_GLES2:
11525 RSurf_ActiveModelEntity(ent, true, true, false);
11527 case RENDERPATH_GL11:
11528 case RENDERPATH_GL13:
11529 case RENDERPATH_GLES1:
11530 RSurf_ActiveModelEntity(ent, true, false, false);
11535 surfaces = model->data_surfaces;
11536 update = model->brushq1.lightmapupdateflags;
11538 // update light styles
11539 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11541 model_brush_lightstyleinfo_t *style;
11542 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11544 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11546 int *list = style->surfacelist;
11547 style->value = r_refdef.scene.lightstylevalue[style->style];
11548 for (j = 0;j < style->numsurfaces;j++)
11549 update[list[j]] = true;
11554 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11558 R_DrawDebugModel();
11559 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11563 rsurface.lightmaptexture = NULL;
11564 rsurface.deluxemaptexture = NULL;
11565 rsurface.uselightmaptexture = false;
11566 rsurface.texture = NULL;
11567 rsurface.rtlight = NULL;
11568 numsurfacelist = 0;
11569 // add visible surfaces to draw list
11570 for (i = 0;i < model->nummodelsurfaces;i++)
11571 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11572 // don't do anything if there were no surfaces
11573 if (!numsurfacelist)
11575 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11578 // update lightmaps if needed
11582 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11587 R_BuildLightMap(ent, surfaces + j);
11592 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11594 R_BuildLightMap(ent, surfaces + j);
11595 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11597 // add to stats if desired
11598 if (r_speeds.integer && !skysurfaces && !depthonly)
11600 r_refdef.stats.entities_surfaces += numsurfacelist;
11601 for (j = 0;j < numsurfacelist;j++)
11602 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11605 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11608 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11610 static texture_t texture;
11611 static msurface_t surface;
11612 const msurface_t *surfacelist = &surface;
11614 // fake enough texture and surface state to render this geometry
11616 texture.update_lastrenderframe = -1; // regenerate this texture
11617 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11618 texture.currentskinframe = skinframe;
11619 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11620 texture.offsetmapping = OFFSETMAPPING_OFF;
11621 texture.offsetscale = 1;
11622 texture.specularscalemod = 1;
11623 texture.specularpowermod = 1;
11625 surface.texture = &texture;
11626 surface.num_triangles = numtriangles;
11627 surface.num_firsttriangle = firsttriangle;
11628 surface.num_vertices = numvertices;
11629 surface.num_firstvertex = firstvertex;
11632 rsurface.texture = R_GetCurrentTexture(surface.texture);
11633 rsurface.lightmaptexture = NULL;
11634 rsurface.deluxemaptexture = NULL;
11635 rsurface.uselightmaptexture = false;
11636 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11639 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)
11641 static msurface_t surface;
11642 const msurface_t *surfacelist = &surface;
11644 // fake enough texture and surface state to render this geometry
11645 surface.texture = texture;
11646 surface.num_triangles = numtriangles;
11647 surface.num_firsttriangle = firsttriangle;
11648 surface.num_vertices = numvertices;
11649 surface.num_firstvertex = firstvertex;
11652 rsurface.texture = R_GetCurrentTexture(surface.texture);
11653 rsurface.lightmaptexture = NULL;
11654 rsurface.deluxemaptexture = NULL;
11655 rsurface.uselightmaptexture = false;
11656 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);