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, this is not yet finished as multisampling is not used"};
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 switch (vid.renderpath)
1916 case RENDERPATH_D3D9:
1918 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1919 R_Mesh_TexBind(GL20TU_FIRST , first );
1920 R_Mesh_TexBind(GL20TU_SECOND, second);
1923 case RENDERPATH_D3D10:
1924 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1926 case RENDERPATH_D3D11:
1927 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1929 case RENDERPATH_GL20:
1930 case RENDERPATH_GLES2:
1931 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
1932 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1933 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1935 case RENDERPATH_GL13:
1936 case RENDERPATH_GLES1:
1937 R_Mesh_TexBind(0, first );
1938 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1939 R_Mesh_TexBind(1, second);
1941 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1943 case RENDERPATH_GL11:
1944 R_Mesh_TexBind(0, first );
1946 case RENDERPATH_SOFT:
1947 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
1948 R_Mesh_TexBind(GL20TU_FIRST , first );
1949 R_Mesh_TexBind(GL20TU_SECOND, second);
1954 void R_SetupShader_DepthOrShadow(qboolean notrippy)
1956 unsigned int permutation = 0;
1957 if (r_trippy.integer && !notrippy)
1958 permutation |= SHADERPERMUTATION_TRIPPY;
1959 switch (vid.renderpath)
1961 case RENDERPATH_D3D9:
1963 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1966 case RENDERPATH_D3D10:
1967 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1969 case RENDERPATH_D3D11:
1970 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1972 case RENDERPATH_GL20:
1973 case RENDERPATH_GLES2:
1974 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1976 case RENDERPATH_GL13:
1977 case RENDERPATH_GLES1:
1978 R_Mesh_TexBind(0, 0);
1979 R_Mesh_TexBind(1, 0);
1981 case RENDERPATH_GL11:
1982 R_Mesh_TexBind(0, 0);
1984 case RENDERPATH_SOFT:
1985 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1990 void R_SetupShader_ShowDepth(qboolean notrippy)
1992 int permutation = 0;
1993 if (r_trippy.integer && !notrippy)
1994 permutation |= SHADERPERMUTATION_TRIPPY;
1995 if (r_trippy.integer)
1996 permutation |= SHADERPERMUTATION_TRIPPY;
1997 switch (vid.renderpath)
1999 case RENDERPATH_D3D9:
2001 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, permutation);
2004 case RENDERPATH_D3D10:
2005 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2007 case RENDERPATH_D3D11:
2008 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2010 case RENDERPATH_GL20:
2011 case RENDERPATH_GLES2:
2012 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, permutation);
2014 case RENDERPATH_GL13:
2015 case RENDERPATH_GLES1:
2017 case RENDERPATH_GL11:
2019 case RENDERPATH_SOFT:
2020 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, permutation);
2025 extern qboolean r_shadow_usingdeferredprepass;
2026 extern cvar_t r_shadow_deferred_8bitrange;
2027 extern rtexture_t *r_shadow_attenuationgradienttexture;
2028 extern rtexture_t *r_shadow_attenuation2dtexture;
2029 extern rtexture_t *r_shadow_attenuation3dtexture;
2030 extern qboolean r_shadow_usingshadowmap2d;
2031 extern qboolean r_shadow_usingshadowmaportho;
2032 extern float r_shadow_shadowmap_texturescale[2];
2033 extern float r_shadow_shadowmap_parameters[4];
2034 extern qboolean r_shadow_shadowmapvsdct;
2035 extern qboolean r_shadow_shadowmapsampler;
2036 extern int r_shadow_shadowmappcf;
2037 extern rtexture_t *r_shadow_shadowmap2dtexture;
2038 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2039 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2040 extern matrix4x4_t r_shadow_shadowmapmatrix;
2041 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2042 extern int r_shadow_prepass_width;
2043 extern int r_shadow_prepass_height;
2044 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2045 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2046 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2047 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2048 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2050 #define BLENDFUNC_ALLOWS_COLORMOD 1
2051 #define BLENDFUNC_ALLOWS_FOG 2
2052 #define BLENDFUNC_ALLOWS_FOG_HACK0 4
2053 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2054 #define BLENDFUNC_ALLOWS_ANYFOG (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2055 static int R_BlendFuncFlags(int src, int dst)
2059 // a blendfunc allows colormod if:
2060 // a) it can never keep the destination pixel invariant, or
2061 // b) it can keep the destination pixel invariant, and still can do so if colormodded
2062 // this is to prevent unintended side effects from colormod
2064 // a blendfunc allows fog if:
2065 // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2066 // this is to prevent unintended side effects from fog
2068 // these checks are the output of fogeval.pl
2070 r |= BLENDFUNC_ALLOWS_COLORMOD;
2071 if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2072 if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2073 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2074 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2075 if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2076 if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2077 if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2078 if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2079 if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2080 if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2081 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2082 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2083 if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2084 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2085 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2086 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2087 if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2088 if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2089 if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2090 if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2091 if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2096 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)
2098 // select a permutation of the lighting shader appropriate to this
2099 // combination of texture, entity, light source, and fogging, only use the
2100 // minimum features necessary to avoid wasting rendering time in the
2101 // fragment shader on features that are not being used
2102 unsigned int permutation = 0;
2103 unsigned int mode = 0;
2105 static float dummy_colormod[3] = {1, 1, 1};
2106 float *colormod = rsurface.colormod;
2108 matrix4x4_t tempmatrix;
2109 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2110 if (r_trippy.integer && !notrippy)
2111 permutation |= SHADERPERMUTATION_TRIPPY;
2112 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2113 permutation |= SHADERPERMUTATION_ALPHAKILL;
2114 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2115 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2116 if (rsurfacepass == RSURFPASS_BACKGROUND)
2118 // distorted background
2119 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2121 mode = SHADERMODE_WATER;
2122 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2124 // this is the right thing to do for wateralpha
2125 GL_BlendFunc(GL_ONE, GL_ZERO);
2126 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2130 // this is the right thing to do for entity alpha
2131 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2132 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2135 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2137 mode = SHADERMODE_REFRACTION;
2138 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2139 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2143 mode = SHADERMODE_GENERIC;
2144 permutation |= SHADERPERMUTATION_DIFFUSE;
2145 GL_BlendFunc(GL_ONE, GL_ZERO);
2146 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2149 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2151 if (r_glsl_offsetmapping.integer)
2153 switch(rsurface.texture->offsetmapping)
2155 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2156 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2157 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2158 case OFFSETMAPPING_OFF: break;
2161 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2162 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2163 // normalmap (deferred prepass), may use alpha test on diffuse
2164 mode = SHADERMODE_DEFERREDGEOMETRY;
2165 GL_BlendFunc(GL_ONE, GL_ZERO);
2166 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2168 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2170 if (r_glsl_offsetmapping.integer)
2172 switch(rsurface.texture->offsetmapping)
2174 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2175 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2176 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2177 case OFFSETMAPPING_OFF: break;
2180 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2181 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2183 mode = SHADERMODE_LIGHTSOURCE;
2184 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2185 permutation |= SHADERPERMUTATION_CUBEFILTER;
2186 if (diffusescale > 0)
2187 permutation |= SHADERPERMUTATION_DIFFUSE;
2188 if (specularscale > 0)
2189 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2190 if (r_refdef.fogenabled)
2191 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2192 if (rsurface.texture->colormapping)
2193 permutation |= SHADERPERMUTATION_COLORMAPPING;
2194 if (r_shadow_usingshadowmap2d)
2196 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2197 if(r_shadow_shadowmapvsdct)
2198 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2200 if (r_shadow_shadowmapsampler)
2201 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2202 if (r_shadow_shadowmappcf > 1)
2203 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2204 else if (r_shadow_shadowmappcf)
2205 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2207 if (rsurface.texture->reflectmasktexture)
2208 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2209 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2210 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2212 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2214 if (r_glsl_offsetmapping.integer)
2216 switch(rsurface.texture->offsetmapping)
2218 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2219 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2220 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2221 case OFFSETMAPPING_OFF: break;
2224 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2225 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2226 // unshaded geometry (fullbright or ambient model lighting)
2227 mode = SHADERMODE_FLATCOLOR;
2228 ambientscale = diffusescale = specularscale = 0;
2229 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2230 permutation |= SHADERPERMUTATION_GLOW;
2231 if (r_refdef.fogenabled)
2232 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2233 if (rsurface.texture->colormapping)
2234 permutation |= SHADERPERMUTATION_COLORMAPPING;
2235 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2237 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2238 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2240 if (r_shadow_shadowmapsampler)
2241 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2242 if (r_shadow_shadowmappcf > 1)
2243 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2244 else if (r_shadow_shadowmappcf)
2245 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2247 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2248 permutation |= SHADERPERMUTATION_REFLECTION;
2249 if (rsurface.texture->reflectmasktexture)
2250 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2251 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2252 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2254 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2256 if (r_glsl_offsetmapping.integer)
2258 switch(rsurface.texture->offsetmapping)
2260 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2261 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2262 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2263 case OFFSETMAPPING_OFF: break;
2266 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2267 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2268 // directional model lighting
2269 mode = SHADERMODE_LIGHTDIRECTION;
2270 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2271 permutation |= SHADERPERMUTATION_GLOW;
2272 permutation |= SHADERPERMUTATION_DIFFUSE;
2273 if (specularscale > 0)
2274 permutation |= SHADERPERMUTATION_SPECULAR;
2275 if (r_refdef.fogenabled)
2276 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2277 if (rsurface.texture->colormapping)
2278 permutation |= SHADERPERMUTATION_COLORMAPPING;
2279 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2281 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2282 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2284 if (r_shadow_shadowmapsampler)
2285 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2286 if (r_shadow_shadowmappcf > 1)
2287 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2288 else if (r_shadow_shadowmappcf)
2289 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2291 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2292 permutation |= SHADERPERMUTATION_REFLECTION;
2293 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2294 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2295 if (rsurface.texture->reflectmasktexture)
2296 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2297 if (r_shadow_bouncegridtexture)
2299 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2300 if (r_shadow_bouncegriddirectional)
2301 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2303 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2304 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2306 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2308 if (r_glsl_offsetmapping.integer)
2310 switch(rsurface.texture->offsetmapping)
2312 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2313 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2314 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2315 case OFFSETMAPPING_OFF: break;
2318 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2319 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2320 // ambient model lighting
2321 mode = SHADERMODE_LIGHTDIRECTION;
2322 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2323 permutation |= SHADERPERMUTATION_GLOW;
2324 if (r_refdef.fogenabled)
2325 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2326 if (rsurface.texture->colormapping)
2327 permutation |= SHADERPERMUTATION_COLORMAPPING;
2328 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2330 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2331 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2333 if (r_shadow_shadowmapsampler)
2334 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2335 if (r_shadow_shadowmappcf > 1)
2336 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2337 else if (r_shadow_shadowmappcf)
2338 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2340 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2341 permutation |= SHADERPERMUTATION_REFLECTION;
2342 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2343 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2344 if (rsurface.texture->reflectmasktexture)
2345 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2346 if (r_shadow_bouncegridtexture)
2348 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2349 if (r_shadow_bouncegriddirectional)
2350 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2352 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2353 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2357 if (r_glsl_offsetmapping.integer)
2359 switch(rsurface.texture->offsetmapping)
2361 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2362 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2363 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2364 case OFFSETMAPPING_OFF: break;
2367 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2368 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2370 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2371 permutation |= SHADERPERMUTATION_GLOW;
2372 if (r_refdef.fogenabled)
2373 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2374 if (rsurface.texture->colormapping)
2375 permutation |= SHADERPERMUTATION_COLORMAPPING;
2376 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2378 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2379 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2381 if (r_shadow_shadowmapsampler)
2382 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2383 if (r_shadow_shadowmappcf > 1)
2384 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2385 else if (r_shadow_shadowmappcf)
2386 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2388 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2389 permutation |= SHADERPERMUTATION_REFLECTION;
2390 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2391 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2392 if (rsurface.texture->reflectmasktexture)
2393 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2394 if (FAKELIGHT_ENABLED)
2396 // fake lightmapping (q1bsp, q3bsp, fullbright map)
2397 mode = SHADERMODE_FAKELIGHT;
2398 permutation |= SHADERPERMUTATION_DIFFUSE;
2399 if (specularscale > 0)
2400 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2402 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2404 // deluxemapping (light direction texture)
2405 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2406 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2408 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2409 permutation |= SHADERPERMUTATION_DIFFUSE;
2410 if (specularscale > 0)
2411 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2413 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2415 // fake deluxemapping (uniform light direction in tangentspace)
2416 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2417 permutation |= SHADERPERMUTATION_DIFFUSE;
2418 if (specularscale > 0)
2419 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2421 else if (rsurface.uselightmaptexture)
2423 // ordinary lightmapping (q1bsp, q3bsp)
2424 mode = SHADERMODE_LIGHTMAP;
2428 // ordinary vertex coloring (q3bsp)
2429 mode = SHADERMODE_VERTEXCOLOR;
2431 if (r_shadow_bouncegridtexture)
2433 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2434 if (r_shadow_bouncegriddirectional)
2435 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2437 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2438 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2440 if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2441 colormod = dummy_colormod;
2442 if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2443 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2444 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2445 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2446 switch(vid.renderpath)
2448 case RENDERPATH_D3D9:
2450 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);
2451 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2452 R_SetupShader_SetPermutationHLSL(mode, permutation);
2453 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2454 if (mode == SHADERMODE_LIGHTSOURCE)
2456 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2457 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2461 if (mode == SHADERMODE_LIGHTDIRECTION)
2463 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2466 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2467 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2468 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2469 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2470 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2472 if (mode == SHADERMODE_LIGHTSOURCE)
2474 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2475 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2476 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2477 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2478 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2480 // additive passes are only darkened by fog, not tinted
2481 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2482 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2486 if (mode == SHADERMODE_FLATCOLOR)
2488 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2490 else if (mode == SHADERMODE_LIGHTDIRECTION)
2492 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]);
2493 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2494 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);
2495 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);
2496 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2497 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2498 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2502 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2503 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[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] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * 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);
2508 // additive passes are only darkened by fog, not tinted
2509 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2510 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2512 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2513 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);
2514 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2515 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2516 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2517 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2518 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2519 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2520 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2521 if (mode == SHADERMODE_WATER)
2522 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2524 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2525 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2526 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2527 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));
2528 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2529 if (rsurface.texture->pantstexture)
2530 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2532 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2533 if (rsurface.texture->shirttexture)
2534 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2536 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2537 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2538 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2539 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2540 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2541 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2542 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2543 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2544 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2545 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2547 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2548 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2550 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2551 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2552 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2553 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2554 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2555 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2556 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2557 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2558 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2559 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2560 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2561 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2562 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2563 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2564 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2565 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2566 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2567 if (rsurfacepass == RSURFPASS_BACKGROUND)
2569 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2570 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2571 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2575 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2577 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2578 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2579 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2580 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2581 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2583 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2584 if (rsurface.rtlight)
2586 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2587 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2592 case RENDERPATH_D3D10:
2593 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2595 case RENDERPATH_D3D11:
2596 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2598 case RENDERPATH_GL20:
2599 case RENDERPATH_GLES2:
2600 if (!vid.useinterleavedarrays)
2602 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);
2603 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2604 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2605 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2606 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2607 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2608 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2609 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2613 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);
2614 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2616 R_SetupShader_SetPermutationGLSL(mode, permutation);
2617 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2618 if (mode == SHADERMODE_LIGHTSOURCE)
2620 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2621 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2622 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2623 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2624 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2625 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);
2627 // additive passes are only darkened by fog, not tinted
2628 if (r_glsl_permutation->loc_FogColor >= 0)
2629 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2630 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2634 if (mode == SHADERMODE_FLATCOLOR)
2636 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2638 else if (mode == SHADERMODE_LIGHTDIRECTION)
2640 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]);
2641 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]);
2642 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);
2643 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);
2644 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);
2645 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]);
2646 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]);
2650 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]);
2651 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]);
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] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * 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);
2656 // additive passes are only darkened by fog, not tinted
2657 if (r_glsl_permutation->loc_FogColor >= 0)
2659 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2660 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2662 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2664 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);
2665 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]);
2666 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]);
2667 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]);
2668 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]);
2669 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2670 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2671 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2672 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]);
2674 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2675 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2676 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2677 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]);
2678 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]);
2680 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2681 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));
2682 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2683 if (r_glsl_permutation->loc_Color_Pants >= 0)
2685 if (rsurface.texture->pantstexture)
2686 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2688 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2690 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2692 if (rsurface.texture->shirttexture)
2693 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2695 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2697 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]);
2698 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2699 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2700 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2701 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2702 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2703 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2704 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2705 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2707 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]);
2708 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2709 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);}
2710 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2712 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
2713 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
2714 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
2715 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
2716 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
2717 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
2718 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
2719 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
2720 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
2721 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
2722 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
2723 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
2724 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
2725 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
2726 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);
2727 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
2728 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
2729 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2730 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2731 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2732 if (rsurfacepass == RSURFPASS_BACKGROUND)
2734 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);
2735 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);
2736 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);
2740 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);
2742 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2743 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2744 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
2745 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
2746 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2748 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture );
2749 if (rsurface.rtlight)
2751 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2752 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2755 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2758 case RENDERPATH_GL11:
2759 case RENDERPATH_GL13:
2760 case RENDERPATH_GLES1:
2762 case RENDERPATH_SOFT:
2763 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);
2764 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2765 R_SetupShader_SetPermutationSoft(mode, permutation);
2766 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2767 if (mode == SHADERMODE_LIGHTSOURCE)
2769 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2770 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2771 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2772 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2773 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2774 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2776 // additive passes are only darkened by fog, not tinted
2777 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2778 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2782 if (mode == SHADERMODE_FLATCOLOR)
2784 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2786 else if (mode == SHADERMODE_LIGHTDIRECTION)
2788 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]);
2789 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2790 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);
2791 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);
2792 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2793 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]);
2794 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2798 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2799 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[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] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * 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);
2804 // additive passes are only darkened by fog, not tinted
2805 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2806 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2808 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2809 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);
2810 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2811 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2812 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]);
2813 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]);
2814 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2815 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2816 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2817 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2819 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2820 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2821 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2822 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2823 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]);
2825 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2826 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));
2827 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2828 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2830 if (rsurface.texture->pantstexture)
2831 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2833 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2835 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2837 if (rsurface.texture->shirttexture)
2838 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2840 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2842 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2843 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2844 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2845 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2846 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2847 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2848 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2849 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2850 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2852 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2853 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2855 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2856 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2857 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2858 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2859 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2860 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2861 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2862 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2863 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2864 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2865 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2866 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2867 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2868 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2869 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2870 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2871 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2872 if (rsurfacepass == RSURFPASS_BACKGROUND)
2874 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2875 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2876 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2880 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2882 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2883 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2884 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2885 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2886 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2888 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2889 if (rsurface.rtlight)
2891 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2892 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2899 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2901 // select a permutation of the lighting shader appropriate to this
2902 // combination of texture, entity, light source, and fogging, only use the
2903 // minimum features necessary to avoid wasting rendering time in the
2904 // fragment shader on features that are not being used
2905 unsigned int permutation = 0;
2906 unsigned int mode = 0;
2907 const float *lightcolorbase = rtlight->currentcolor;
2908 float ambientscale = rtlight->ambientscale;
2909 float diffusescale = rtlight->diffusescale;
2910 float specularscale = rtlight->specularscale;
2911 // this is the location of the light in view space
2912 vec3_t viewlightorigin;
2913 // this transforms from view space (camera) to light space (cubemap)
2914 matrix4x4_t viewtolight;
2915 matrix4x4_t lighttoview;
2916 float viewtolight16f[16];
2917 float range = 1.0f / r_shadow_deferred_8bitrange.value;
2919 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2920 if (rtlight->currentcubemap != r_texture_whitecube)
2921 permutation |= SHADERPERMUTATION_CUBEFILTER;
2922 if (diffusescale > 0)
2923 permutation |= SHADERPERMUTATION_DIFFUSE;
2924 if (specularscale > 0 && r_shadow_gloss.integer > 0)
2925 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2926 if (r_shadow_usingshadowmap2d)
2928 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2929 if (r_shadow_shadowmapvsdct)
2930 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2932 if (r_shadow_shadowmapsampler)
2933 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2934 if (r_shadow_shadowmappcf > 1)
2935 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2936 else if (r_shadow_shadowmappcf)
2937 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2939 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2940 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2941 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2942 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2943 switch(vid.renderpath)
2945 case RENDERPATH_D3D9:
2947 R_SetupShader_SetPermutationHLSL(mode, permutation);
2948 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2949 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
2950 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2951 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2952 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2953 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2954 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2955 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2956 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2957 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2959 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2960 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthcolortexture );
2961 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2962 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2963 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dcolortexture );
2964 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2967 case RENDERPATH_D3D10:
2968 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2970 case RENDERPATH_D3D11:
2971 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2973 case RENDERPATH_GL20:
2974 case RENDERPATH_GLES2:
2975 R_SetupShader_SetPermutationGLSL(mode, permutation);
2976 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2977 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
2978 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);
2979 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);
2980 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);
2981 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]);
2982 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]);
2983 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));
2984 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]);
2985 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
2987 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2988 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2989 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2990 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2991 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );
2992 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2994 case RENDERPATH_GL11:
2995 case RENDERPATH_GL13:
2996 case RENDERPATH_GLES1:
2998 case RENDERPATH_SOFT:
2999 R_SetupShader_SetPermutationGLSL(mode, permutation);
3000 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3001 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
3002 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
3003 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
3004 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3005 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3006 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]);
3007 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));
3008 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3009 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3011 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3012 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
3013 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3014 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3015 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
3016 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3021 #define SKINFRAME_HASH 1024
3025 int loadsequence; // incremented each level change
3026 memexpandablearray_t array;
3027 skinframe_t *hash[SKINFRAME_HASH];
3030 r_skinframe_t r_skinframe;
3032 void R_SkinFrame_PrepareForPurge(void)
3034 r_skinframe.loadsequence++;
3035 // wrap it without hitting zero
3036 if (r_skinframe.loadsequence >= 200)
3037 r_skinframe.loadsequence = 1;
3040 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3044 // mark the skinframe as used for the purging code
3045 skinframe->loadsequence = r_skinframe.loadsequence;
3048 void R_SkinFrame_Purge(void)
3052 for (i = 0;i < SKINFRAME_HASH;i++)
3054 for (s = r_skinframe.hash[i];s;s = s->next)
3056 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3058 if (s->merged == s->base)
3060 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3061 R_PurgeTexture(s->stain );s->stain = NULL;
3062 R_PurgeTexture(s->merged);s->merged = NULL;
3063 R_PurgeTexture(s->base );s->base = NULL;
3064 R_PurgeTexture(s->pants );s->pants = NULL;
3065 R_PurgeTexture(s->shirt );s->shirt = NULL;
3066 R_PurgeTexture(s->nmap );s->nmap = NULL;
3067 R_PurgeTexture(s->gloss );s->gloss = NULL;
3068 R_PurgeTexture(s->glow );s->glow = NULL;
3069 R_PurgeTexture(s->fog );s->fog = NULL;
3070 R_PurgeTexture(s->reflect);s->reflect = NULL;
3071 s->loadsequence = 0;
3077 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3079 char basename[MAX_QPATH];
3081 Image_StripImageExtension(name, basename, sizeof(basename));
3083 if( last == NULL ) {
3085 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3086 item = r_skinframe.hash[hashindex];
3091 // linearly search through the hash bucket
3092 for( ; item ; item = item->next ) {
3093 if( !strcmp( item->basename, basename ) ) {
3100 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3104 char basename[MAX_QPATH];
3106 Image_StripImageExtension(name, basename, sizeof(basename));
3108 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3109 for (item = r_skinframe.hash[hashindex];item;item = item->next)
3110 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3114 rtexture_t *dyntexture;
3115 // check whether its a dynamic texture
3116 dyntexture = CL_GetDynTexture( basename );
3117 if (!add && !dyntexture)
3119 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3120 memset(item, 0, sizeof(*item));
3121 strlcpy(item->basename, basename, sizeof(item->basename));
3122 item->base = dyntexture; // either NULL or dyntexture handle
3123 item->textureflags = textureflags;
3124 item->comparewidth = comparewidth;
3125 item->compareheight = compareheight;
3126 item->comparecrc = comparecrc;
3127 item->next = r_skinframe.hash[hashindex];
3128 r_skinframe.hash[hashindex] = item;
3130 else if( item->base == NULL )
3132 rtexture_t *dyntexture;
3133 // check whether its a dynamic texture
3134 // 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]
3135 dyntexture = CL_GetDynTexture( basename );
3136 item->base = dyntexture; // either NULL or dyntexture handle
3139 R_SkinFrame_MarkUsed(item);
3143 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3145 unsigned long long avgcolor[5], wsum; \
3153 for(pix = 0; pix < cnt; ++pix) \
3156 for(comp = 0; comp < 3; ++comp) \
3158 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3161 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3163 for(comp = 0; comp < 3; ++comp) \
3164 avgcolor[comp] += getpixel * w; \
3167 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3168 avgcolor[4] += getpixel; \
3170 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3172 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3173 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3174 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3175 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3178 extern cvar_t gl_picmip;
3179 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3182 unsigned char *pixels;
3183 unsigned char *bumppixels;
3184 unsigned char *basepixels = NULL;
3185 int basepixels_width = 0;
3186 int basepixels_height = 0;
3187 skinframe_t *skinframe;
3188 rtexture_t *ddsbase = NULL;
3189 qboolean ddshasalpha = false;
3190 float ddsavgcolor[4];
3191 char basename[MAX_QPATH];
3192 int miplevel = R_PicmipForFlags(textureflags);
3193 int savemiplevel = miplevel;
3196 if (cls.state == ca_dedicated)
3199 // return an existing skinframe if already loaded
3200 // if loading of the first image fails, don't make a new skinframe as it
3201 // would cause all future lookups of this to be missing
3202 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3203 if (skinframe && skinframe->base)
3206 Image_StripImageExtension(name, basename, sizeof(basename));
3208 // check for DDS texture file first
3209 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3211 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3212 if (basepixels == NULL)
3216 // FIXME handle miplevel
3218 if (developer_loading.integer)
3219 Con_Printf("loading skin \"%s\"\n", name);
3221 // we've got some pixels to store, so really allocate this new texture now
3223 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3224 skinframe->stain = NULL;
3225 skinframe->merged = NULL;
3226 skinframe->base = NULL;
3227 skinframe->pants = NULL;
3228 skinframe->shirt = NULL;
3229 skinframe->nmap = NULL;
3230 skinframe->gloss = NULL;
3231 skinframe->glow = NULL;
3232 skinframe->fog = NULL;
3233 skinframe->reflect = NULL;
3234 skinframe->hasalpha = false;
3238 skinframe->base = ddsbase;
3239 skinframe->hasalpha = ddshasalpha;
3240 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3241 if (r_loadfog && skinframe->hasalpha)
3242 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3243 //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]);
3247 basepixels_width = image_width;
3248 basepixels_height = image_height;
3249 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);
3250 if (textureflags & TEXF_ALPHA)
3252 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3254 if (basepixels[j] < 255)
3256 skinframe->hasalpha = true;
3260 if (r_loadfog && skinframe->hasalpha)
3262 // has transparent pixels
3263 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3264 for (j = 0;j < image_width * image_height * 4;j += 4)
3269 pixels[j+3] = basepixels[j+3];
3271 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);
3275 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3276 //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]);
3277 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3278 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3279 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3280 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3285 mymiplevel = savemiplevel;
3286 if (r_loadnormalmap)
3287 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);
3288 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3290 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3291 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3292 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3293 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3296 // _norm is the name used by tenebrae and has been adopted as standard
3297 if (r_loadnormalmap && skinframe->nmap == NULL)
3299 mymiplevel = savemiplevel;
3300 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3302 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);
3306 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3308 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3309 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3310 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);
3312 Mem_Free(bumppixels);
3314 else if (r_shadow_bumpscale_basetexture.value > 0)
3316 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3317 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3318 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);
3321 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3322 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3325 // _luma is supported only for tenebrae compatibility
3326 // _glow is the preferred name
3327 mymiplevel = savemiplevel;
3328 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))))
3330 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);
3331 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3332 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3333 Mem_Free(pixels);pixels = NULL;
3336 mymiplevel = savemiplevel;
3337 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3339 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);
3340 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3341 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3346 mymiplevel = savemiplevel;
3347 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3349 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);
3350 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3351 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3356 mymiplevel = savemiplevel;
3357 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3359 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);
3360 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3361 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3366 mymiplevel = savemiplevel;
3367 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3369 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);
3370 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3371 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3377 Mem_Free(basepixels);
3382 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3383 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3386 unsigned char *temp1, *temp2;
3387 skinframe_t *skinframe;
3389 if (cls.state == ca_dedicated)
3392 // if already loaded just return it, otherwise make a new skinframe
3393 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3394 if (skinframe && skinframe->base)
3397 skinframe->stain = NULL;
3398 skinframe->merged = NULL;
3399 skinframe->base = NULL;
3400 skinframe->pants = NULL;
3401 skinframe->shirt = NULL;
3402 skinframe->nmap = NULL;
3403 skinframe->gloss = NULL;
3404 skinframe->glow = NULL;
3405 skinframe->fog = NULL;
3406 skinframe->reflect = NULL;
3407 skinframe->hasalpha = false;
3409 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3413 if (developer_loading.integer)
3414 Con_Printf("loading 32bit skin \"%s\"\n", name);
3416 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3418 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3419 temp2 = temp1 + width * height * 4;
3420 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3421 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);
3424 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3425 if (textureflags & TEXF_ALPHA)
3427 for (i = 3;i < width * height * 4;i += 4)
3429 if (skindata[i] < 255)
3431 skinframe->hasalpha = true;
3435 if (r_loadfog && skinframe->hasalpha)
3437 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3438 memcpy(fogpixels, skindata, width * height * 4);
3439 for (i = 0;i < width * height * 4;i += 4)
3440 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3441 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3442 Mem_Free(fogpixels);
3446 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3447 //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]);
3452 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3456 skinframe_t *skinframe;
3458 if (cls.state == ca_dedicated)
3461 // if already loaded just return it, otherwise make a new skinframe
3462 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3463 if (skinframe && skinframe->base)
3466 skinframe->stain = NULL;
3467 skinframe->merged = NULL;
3468 skinframe->base = NULL;
3469 skinframe->pants = NULL;
3470 skinframe->shirt = NULL;
3471 skinframe->nmap = NULL;
3472 skinframe->gloss = NULL;
3473 skinframe->glow = NULL;
3474 skinframe->fog = NULL;
3475 skinframe->reflect = NULL;
3476 skinframe->hasalpha = false;
3478 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3482 if (developer_loading.integer)
3483 Con_Printf("loading quake skin \"%s\"\n", name);
3485 // 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)
3486 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3487 memcpy(skinframe->qpixels, skindata, width*height);
3488 skinframe->qwidth = width;
3489 skinframe->qheight = height;
3492 for (i = 0;i < width * height;i++)
3493 featuresmask |= palette_featureflags[skindata[i]];
3495 skinframe->hasalpha = false;
3496 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3497 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3498 skinframe->qgeneratemerged = true;
3499 skinframe->qgeneratebase = skinframe->qhascolormapping;
3500 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3502 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3503 //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]);
3508 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3512 unsigned char *skindata;
3514 if (!skinframe->qpixels)
3517 if (!skinframe->qhascolormapping)
3518 colormapped = false;
3522 if (!skinframe->qgeneratebase)
3527 if (!skinframe->qgeneratemerged)
3531 width = skinframe->qwidth;
3532 height = skinframe->qheight;
3533 skindata = skinframe->qpixels;
3535 if (skinframe->qgeneratenmap)
3537 unsigned char *temp1, *temp2;
3538 skinframe->qgeneratenmap = false;
3539 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3540 temp2 = temp1 + width * height * 4;
3541 // use either a custom palette or the quake palette
3542 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3543 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3544 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);
3548 if (skinframe->qgenerateglow)
3550 skinframe->qgenerateglow = false;
3551 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
3556 skinframe->qgeneratebase = false;
3557 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);
3558 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);
3559 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);
3563 skinframe->qgeneratemerged = false;
3564 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);
3567 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3569 Mem_Free(skinframe->qpixels);
3570 skinframe->qpixels = NULL;
3574 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)
3577 skinframe_t *skinframe;
3579 if (cls.state == ca_dedicated)
3582 // if already loaded just return it, otherwise make a new skinframe
3583 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3584 if (skinframe && skinframe->base)
3587 skinframe->stain = NULL;
3588 skinframe->merged = NULL;
3589 skinframe->base = NULL;
3590 skinframe->pants = NULL;
3591 skinframe->shirt = NULL;
3592 skinframe->nmap = NULL;
3593 skinframe->gloss = NULL;
3594 skinframe->glow = NULL;
3595 skinframe->fog = NULL;
3596 skinframe->reflect = NULL;
3597 skinframe->hasalpha = false;
3599 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3603 if (developer_loading.integer)
3604 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3606 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3607 if (textureflags & TEXF_ALPHA)
3609 for (i = 0;i < width * height;i++)
3611 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3613 skinframe->hasalpha = true;
3617 if (r_loadfog && skinframe->hasalpha)
3618 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3621 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3622 //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]);
3627 skinframe_t *R_SkinFrame_LoadMissing(void)
3629 skinframe_t *skinframe;
3631 if (cls.state == ca_dedicated)
3634 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3635 skinframe->stain = NULL;
3636 skinframe->merged = NULL;
3637 skinframe->base = NULL;
3638 skinframe->pants = NULL;
3639 skinframe->shirt = NULL;
3640 skinframe->nmap = NULL;
3641 skinframe->gloss = NULL;
3642 skinframe->glow = NULL;
3643 skinframe->fog = NULL;
3644 skinframe->reflect = NULL;
3645 skinframe->hasalpha = false;
3647 skinframe->avgcolor[0] = rand() / RAND_MAX;
3648 skinframe->avgcolor[1] = rand() / RAND_MAX;
3649 skinframe->avgcolor[2] = rand() / RAND_MAX;
3650 skinframe->avgcolor[3] = 1;
3655 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3656 typedef struct suffixinfo_s
3659 qboolean flipx, flipy, flipdiagonal;
3662 static suffixinfo_t suffix[3][6] =
3665 {"px", false, false, false},
3666 {"nx", false, false, false},
3667 {"py", false, false, false},
3668 {"ny", false, false, false},
3669 {"pz", false, false, false},
3670 {"nz", false, false, false}
3673 {"posx", false, false, false},
3674 {"negx", false, false, false},
3675 {"posy", false, false, false},
3676 {"negy", false, false, false},
3677 {"posz", false, false, false},
3678 {"negz", false, false, false}
3681 {"rt", true, false, true},
3682 {"lf", false, true, true},
3683 {"ft", true, true, false},
3684 {"bk", false, false, false},
3685 {"up", true, false, true},
3686 {"dn", true, false, true}
3690 static int componentorder[4] = {0, 1, 2, 3};
3692 rtexture_t *R_LoadCubemap(const char *basename)
3694 int i, j, cubemapsize;
3695 unsigned char *cubemappixels, *image_buffer;
3696 rtexture_t *cubemaptexture;
3698 // must start 0 so the first loadimagepixels has no requested width/height
3700 cubemappixels = NULL;
3701 cubemaptexture = NULL;
3702 // keep trying different suffix groups (posx, px, rt) until one loads
3703 for (j = 0;j < 3 && !cubemappixels;j++)
3705 // load the 6 images in the suffix group
3706 for (i = 0;i < 6;i++)
3708 // generate an image name based on the base and and suffix
3709 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3711 if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3713 // an image loaded, make sure width and height are equal
3714 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3716 // if this is the first image to load successfully, allocate the cubemap memory
3717 if (!cubemappixels && image_width >= 1)
3719 cubemapsize = image_width;
3720 // note this clears to black, so unavailable sides are black
3721 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3723 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3725 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);
3728 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3730 Mem_Free(image_buffer);
3734 // if a cubemap loaded, upload it
3737 if (developer_loading.integer)
3738 Con_Printf("loading cubemap \"%s\"\n", basename);
3740 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);
3741 Mem_Free(cubemappixels);
3745 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3746 if (developer_loading.integer)
3748 Con_Printf("(tried tried images ");
3749 for (j = 0;j < 3;j++)
3750 for (i = 0;i < 6;i++)
3751 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3752 Con_Print(" and was unable to find any of them).\n");
3755 return cubemaptexture;
3758 rtexture_t *R_GetCubemap(const char *basename)
3761 for (i = 0;i < r_texture_numcubemaps;i++)
3762 if (r_texture_cubemaps[i] != NULL)
3763 if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3764 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3765 if (i >= MAX_CUBEMAPS || !r_main_mempool)
3766 return r_texture_whitecube;
3767 r_texture_numcubemaps++;
3768 r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3769 strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3770 r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3771 return r_texture_cubemaps[i]->texture;
3774 void R_FreeCubemap(const char *basename)
3778 for (i = 0;i < r_texture_numcubemaps;i++)
3780 if (r_texture_cubemaps[i] != NULL)
3782 if (r_texture_cubemaps[i]->texture)
3784 if (developer_loading.integer)
3785 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3786 R_FreeTexture(r_texture_cubemaps[i]->texture);
3787 Mem_Free(r_texture_cubemaps[i]);
3788 r_texture_cubemaps[i] = NULL;
3794 void R_FreeCubemaps(void)
3797 for (i = 0;i < r_texture_numcubemaps;i++)
3799 if (developer_loading.integer)
3800 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3801 if (r_texture_cubemaps[i] != NULL)
3803 if (r_texture_cubemaps[i]->texture)
3804 R_FreeTexture(r_texture_cubemaps[i]->texture);
3805 Mem_Free(r_texture_cubemaps[i]);
3808 r_texture_numcubemaps = 0;
3811 void R_Main_FreeViewCache(void)
3813 if (r_refdef.viewcache.entityvisible)
3814 Mem_Free(r_refdef.viewcache.entityvisible);
3815 if (r_refdef.viewcache.world_pvsbits)
3816 Mem_Free(r_refdef.viewcache.world_pvsbits);
3817 if (r_refdef.viewcache.world_leafvisible)
3818 Mem_Free(r_refdef.viewcache.world_leafvisible);
3819 if (r_refdef.viewcache.world_surfacevisible)
3820 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3821 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3824 void R_Main_ResizeViewCache(void)
3826 int numentities = r_refdef.scene.numentities;
3827 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3828 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3829 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3830 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3831 if (r_refdef.viewcache.maxentities < numentities)
3833 r_refdef.viewcache.maxentities = numentities;
3834 if (r_refdef.viewcache.entityvisible)
3835 Mem_Free(r_refdef.viewcache.entityvisible);
3836 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3838 if (r_refdef.viewcache.world_numclusters != numclusters)
3840 r_refdef.viewcache.world_numclusters = numclusters;
3841 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3842 if (r_refdef.viewcache.world_pvsbits)
3843 Mem_Free(r_refdef.viewcache.world_pvsbits);
3844 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3846 if (r_refdef.viewcache.world_numleafs != numleafs)
3848 r_refdef.viewcache.world_numleafs = numleafs;
3849 if (r_refdef.viewcache.world_leafvisible)
3850 Mem_Free(r_refdef.viewcache.world_leafvisible);
3851 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3853 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3855 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3856 if (r_refdef.viewcache.world_surfacevisible)
3857 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3858 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3862 extern rtexture_t *loadingscreentexture;
3863 void gl_main_start(void)
3865 loadingscreentexture = NULL;
3866 r_texture_blanknormalmap = NULL;
3867 r_texture_white = NULL;
3868 r_texture_grey128 = NULL;
3869 r_texture_black = NULL;
3870 r_texture_whitecube = NULL;
3871 r_texture_normalizationcube = NULL;
3872 r_texture_fogattenuation = NULL;
3873 r_texture_fogheighttexture = NULL;
3874 r_texture_gammaramps = NULL;
3875 r_texture_numcubemaps = 0;
3877 r_loaddds = r_texture_dds_load.integer != 0;
3878 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3880 switch(vid.renderpath)
3882 case RENDERPATH_GL20:
3883 case RENDERPATH_D3D9:
3884 case RENDERPATH_D3D10:
3885 case RENDERPATH_D3D11:
3886 case RENDERPATH_SOFT:
3887 case RENDERPATH_GLES2:
3888 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3889 Cvar_SetValueQuick(&gl_combine, 1);
3890 Cvar_SetValueQuick(&r_glsl, 1);
3891 r_loadnormalmap = true;
3895 case RENDERPATH_GL13:
3896 case RENDERPATH_GLES1:
3897 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3898 Cvar_SetValueQuick(&gl_combine, 1);
3899 Cvar_SetValueQuick(&r_glsl, 0);
3900 r_loadnormalmap = false;
3901 r_loadgloss = false;
3904 case RENDERPATH_GL11:
3905 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3906 Cvar_SetValueQuick(&gl_combine, 0);
3907 Cvar_SetValueQuick(&r_glsl, 0);
3908 r_loadnormalmap = false;
3909 r_loadgloss = false;
3915 R_FrameData_Reset();
3919 memset(r_queries, 0, sizeof(r_queries));
3921 r_qwskincache = NULL;
3922 r_qwskincache_size = 0;
3924 // due to caching of texture_t references, the collision cache must be reset
3925 Collision_Cache_Reset(true);
3927 // set up r_skinframe loading system for textures
3928 memset(&r_skinframe, 0, sizeof(r_skinframe));
3929 r_skinframe.loadsequence = 1;
3930 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3932 r_main_texturepool = R_AllocTexturePool();
3933 R_BuildBlankTextures();
3935 if (vid.support.arb_texture_cube_map)
3938 R_BuildNormalizationCube();
3940 r_texture_fogattenuation = NULL;
3941 r_texture_fogheighttexture = NULL;
3942 r_texture_gammaramps = NULL;
3943 //r_texture_fogintensity = NULL;
3944 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3945 memset(&r_waterstate, 0, sizeof(r_waterstate));
3946 r_glsl_permutation = NULL;
3947 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3948 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3949 glslshaderstring = NULL;
3951 r_hlsl_permutation = NULL;
3952 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3953 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
3955 hlslshaderstring = NULL;
3956 memset(&r_svbsp, 0, sizeof (r_svbsp));
3958 memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
3959 r_texture_numcubemaps = 0;
3961 r_refdef.fogmasktable_density = 0;
3964 void gl_main_shutdown(void)
3967 R_FrameData_Reset();
3969 R_Main_FreeViewCache();
3971 switch(vid.renderpath)
3973 case RENDERPATH_GL11:
3974 case RENDERPATH_GL13:
3975 case RENDERPATH_GL20:
3976 case RENDERPATH_GLES1:
3977 case RENDERPATH_GLES2:
3979 qglDeleteQueriesARB(r_maxqueries, r_queries);
3981 case RENDERPATH_D3D9:
3982 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3984 case RENDERPATH_D3D10:
3985 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3987 case RENDERPATH_D3D11:
3988 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3990 case RENDERPATH_SOFT:
3996 memset(r_queries, 0, sizeof(r_queries));
3998 r_qwskincache = NULL;
3999 r_qwskincache_size = 0;
4001 // clear out the r_skinframe state
4002 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4003 memset(&r_skinframe, 0, sizeof(r_skinframe));
4006 Mem_Free(r_svbsp.nodes);
4007 memset(&r_svbsp, 0, sizeof (r_svbsp));
4008 R_FreeTexturePool(&r_main_texturepool);
4009 loadingscreentexture = NULL;
4010 r_texture_blanknormalmap = NULL;
4011 r_texture_white = NULL;
4012 r_texture_grey128 = NULL;
4013 r_texture_black = NULL;
4014 r_texture_whitecube = NULL;
4015 r_texture_normalizationcube = NULL;
4016 r_texture_fogattenuation = NULL;
4017 r_texture_fogheighttexture = NULL;
4018 r_texture_gammaramps = NULL;
4019 r_texture_numcubemaps = 0;
4020 //r_texture_fogintensity = NULL;
4021 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4022 memset(&r_waterstate, 0, sizeof(r_waterstate));
4025 r_glsl_permutation = NULL;
4026 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4027 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4028 glslshaderstring = NULL;
4030 r_hlsl_permutation = NULL;
4031 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4032 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4034 hlslshaderstring = NULL;
4037 extern void CL_ParseEntityLump(char *entitystring);
4038 void gl_main_newmap(void)
4040 // FIXME: move this code to client
4041 char *entities, entname[MAX_QPATH];
4043 Mem_Free(r_qwskincache);
4044 r_qwskincache = NULL;
4045 r_qwskincache_size = 0;
4048 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4049 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4051 CL_ParseEntityLump(entities);
4055 if (cl.worldmodel->brush.entities)
4056 CL_ParseEntityLump(cl.worldmodel->brush.entities);
4058 R_Main_FreeViewCache();
4060 R_FrameData_Reset();
4063 void GL_Main_Init(void)
4065 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4067 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4068 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4069 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4070 if (gamemode == GAME_NEHAHRA)
4072 Cvar_RegisterVariable (&gl_fogenable);
4073 Cvar_RegisterVariable (&gl_fogdensity);
4074 Cvar_RegisterVariable (&gl_fogred);
4075 Cvar_RegisterVariable (&gl_foggreen);
4076 Cvar_RegisterVariable (&gl_fogblue);
4077 Cvar_RegisterVariable (&gl_fogstart);
4078 Cvar_RegisterVariable (&gl_fogend);
4079 Cvar_RegisterVariable (&gl_skyclip);
4081 Cvar_RegisterVariable(&r_motionblur);
4082 Cvar_RegisterVariable(&r_motionblur_maxblur);
4083 Cvar_RegisterVariable(&r_motionblur_bmin);
4084 Cvar_RegisterVariable(&r_motionblur_vmin);
4085 Cvar_RegisterVariable(&r_motionblur_vmax);
4086 Cvar_RegisterVariable(&r_motionblur_vcoeff);
4087 Cvar_RegisterVariable(&r_motionblur_randomize);
4088 Cvar_RegisterVariable(&r_damageblur);
4089 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4090 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4091 Cvar_RegisterVariable(&r_equalize_entities_by);
4092 Cvar_RegisterVariable(&r_equalize_entities_to);
4093 Cvar_RegisterVariable(&r_depthfirst);
4094 Cvar_RegisterVariable(&r_useinfinitefarclip);
4095 Cvar_RegisterVariable(&r_farclip_base);
4096 Cvar_RegisterVariable(&r_farclip_world);
4097 Cvar_RegisterVariable(&r_nearclip);
4098 Cvar_RegisterVariable(&r_deformvertexes);
4099 Cvar_RegisterVariable(&r_transparent);
4100 Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4101 Cvar_RegisterVariable(&r_showoverdraw);
4102 Cvar_RegisterVariable(&r_showbboxes);
4103 Cvar_RegisterVariable(&r_showsurfaces);
4104 Cvar_RegisterVariable(&r_showtris);
4105 Cvar_RegisterVariable(&r_shownormals);
4106 Cvar_RegisterVariable(&r_showlighting);
4107 Cvar_RegisterVariable(&r_showshadowvolumes);
4108 Cvar_RegisterVariable(&r_showcollisionbrushes);
4109 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4110 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4111 Cvar_RegisterVariable(&r_showdisabledepthtest);
4112 Cvar_RegisterVariable(&r_drawportals);
4113 Cvar_RegisterVariable(&r_drawentities);
4114 Cvar_RegisterVariable(&r_draw2d);
4115 Cvar_RegisterVariable(&r_drawworld);
4116 Cvar_RegisterVariable(&r_cullentities_trace);
4117 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4118 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4119 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4120 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4121 Cvar_RegisterVariable(&r_drawviewmodel);
4122 Cvar_RegisterVariable(&r_drawexteriormodel);
4123 Cvar_RegisterVariable(&r_speeds);
4124 Cvar_RegisterVariable(&r_fullbrights);
4125 Cvar_RegisterVariable(&r_wateralpha);
4126 Cvar_RegisterVariable(&r_dynamic);
4127 Cvar_RegisterVariable(&r_fakelight);
4128 Cvar_RegisterVariable(&r_fakelight_intensity);
4129 Cvar_RegisterVariable(&r_fullbright);
4130 Cvar_RegisterVariable(&r_shadows);
4131 Cvar_RegisterVariable(&r_shadows_darken);
4132 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4133 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4134 Cvar_RegisterVariable(&r_shadows_throwdistance);
4135 Cvar_RegisterVariable(&r_shadows_throwdirection);
4136 Cvar_RegisterVariable(&r_shadows_focus);
4137 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4138 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4139 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4140 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4141 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4142 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4143 Cvar_RegisterVariable(&r_fog_exp2);
4144 Cvar_RegisterVariable(&r_fog_clear);
4145 Cvar_RegisterVariable(&r_drawfog);
4146 Cvar_RegisterVariable(&r_transparentdepthmasking);
4147 Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4148 Cvar_RegisterVariable(&r_transparent_sortarraysize);
4149 Cvar_RegisterVariable(&r_texture_dds_load);
4150 Cvar_RegisterVariable(&r_texture_dds_save);
4151 Cvar_RegisterVariable(&r_textureunits);
4152 Cvar_RegisterVariable(&gl_combine);
4153 Cvar_RegisterVariable(&r_viewfbo);
4154 Cvar_RegisterVariable(&r_viewscale);
4155 Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4156 Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4157 Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4158 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4159 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4160 Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4161 Cvar_RegisterVariable(&r_glsl);
4162 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4163 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4164 Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4165 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4166 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4167 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4168 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4169 Cvar_RegisterVariable(&r_glsl_postprocess);
4170 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4171 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4172 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4173 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4174 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4175 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4176 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4177 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4179 Cvar_RegisterVariable(&r_water);
4180 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4181 Cvar_RegisterVariable(&r_water_clippingplanebias);
4182 Cvar_RegisterVariable(&r_water_refractdistort);
4183 Cvar_RegisterVariable(&r_water_reflectdistort);
4184 Cvar_RegisterVariable(&r_water_scissormode);
4185 Cvar_RegisterVariable(&r_water_lowquality);
4187 Cvar_RegisterVariable(&r_lerpsprites);
4188 Cvar_RegisterVariable(&r_lerpmodels);
4189 Cvar_RegisterVariable(&r_lerplightstyles);
4190 Cvar_RegisterVariable(&r_waterscroll);
4191 Cvar_RegisterVariable(&r_bloom);
4192 Cvar_RegisterVariable(&r_bloom_colorscale);
4193 Cvar_RegisterVariable(&r_bloom_brighten);
4194 Cvar_RegisterVariable(&r_bloom_blur);
4195 Cvar_RegisterVariable(&r_bloom_resolution);
4196 Cvar_RegisterVariable(&r_bloom_colorexponent);
4197 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4198 Cvar_RegisterVariable(&r_hdr);
4199 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4200 Cvar_RegisterVariable(&r_hdr_glowintensity);
4201 Cvar_RegisterVariable(&r_hdr_range);
4202 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4203 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4204 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4205 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4206 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4207 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4208 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4209 Cvar_RegisterVariable(&developer_texturelogging);
4210 Cvar_RegisterVariable(&gl_lightmaps);
4211 Cvar_RegisterVariable(&r_test);
4212 Cvar_RegisterVariable(&r_glsl_saturation);
4213 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4214 Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4215 Cvar_RegisterVariable(&r_framedatasize);
4216 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4217 Cvar_SetValue("r_fullbrights", 0);
4218 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4221 extern void R_Textures_Init(void);
4222 extern void GL_Draw_Init(void);
4223 extern void GL_Main_Init(void);
4224 extern void R_Shadow_Init(void);
4225 extern void R_Sky_Init(void);
4226 extern void GL_Surf_Init(void);
4227 extern void R_Particles_Init(void);
4228 extern void R_Explosion_Init(void);
4229 extern void gl_backend_init(void);
4230 extern void Sbar_Init(void);
4231 extern void R_LightningBeams_Init(void);
4232 extern void Mod_RenderInit(void);
4233 extern void Font_Init(void);
4235 void Render_Init(void)
4248 R_LightningBeams_Init();
4257 extern char *ENGINE_EXTENSIONS;
4260 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4261 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4262 gl_version = (const char *)qglGetString(GL_VERSION);
4263 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4267 if (!gl_platformextensions)
4268 gl_platformextensions = "";
4270 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4271 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4272 Con_Printf("GL_VERSION: %s\n", gl_version);
4273 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4274 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4276 VID_CheckExtensions();
4278 // LordHavoc: report supported extensions
4279 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4281 // clear to black (loading plaque will be seen over this)
4282 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4285 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4289 if (r_trippy.integer)
4291 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4293 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4296 p = r_refdef.view.frustum + i;
4301 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4305 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4309 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4313 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4317 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4321 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4325 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4329 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4337 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4341 if (r_trippy.integer)
4343 for (i = 0;i < numplanes;i++)
4350 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4354 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4358 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4362 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4366 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4370 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4374 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4378 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4386 //==================================================================================
4388 // LordHavoc: this stores temporary data used within the same frame
4390 typedef struct r_framedata_mem_s
4392 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4393 size_t size; // how much usable space
4394 size_t current; // how much space in use
4395 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4396 size_t wantedsize; // how much space was allocated
4397 unsigned char *data; // start of real data (16byte aligned)
4401 static r_framedata_mem_t *r_framedata_mem;
4403 void R_FrameData_Reset(void)
4405 while (r_framedata_mem)
4407 r_framedata_mem_t *next = r_framedata_mem->purge;
4408 Mem_Free(r_framedata_mem);
4409 r_framedata_mem = next;
4413 void R_FrameData_Resize(void)
4416 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4417 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4418 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4420 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4421 newmem->wantedsize = wantedsize;
4422 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4423 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4424 newmem->current = 0;
4426 newmem->purge = r_framedata_mem;
4427 r_framedata_mem = newmem;
4431 void R_FrameData_NewFrame(void)
4433 R_FrameData_Resize();
4434 if (!r_framedata_mem)
4436 // if we ran out of space on the last frame, free the old memory now
4437 while (r_framedata_mem->purge)
4439 // repeatedly remove the second item in the list, leaving only head
4440 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4441 Mem_Free(r_framedata_mem->purge);
4442 r_framedata_mem->purge = next;
4444 // reset the current mem pointer
4445 r_framedata_mem->current = 0;
4446 r_framedata_mem->mark = 0;
4449 void *R_FrameData_Alloc(size_t size)
4453 // align to 16 byte boundary - the data pointer is already aligned, so we
4454 // only need to ensure the size of every allocation is also aligned
4455 size = (size + 15) & ~15;
4457 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4459 // emergency - we ran out of space, allocate more memory
4460 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4461 R_FrameData_Resize();
4464 data = r_framedata_mem->data + r_framedata_mem->current;
4465 r_framedata_mem->current += size;
4467 // count the usage for stats
4468 r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4469 r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4471 return (void *)data;
4474 void *R_FrameData_Store(size_t size, void *data)
4476 void *d = R_FrameData_Alloc(size);
4478 memcpy(d, data, size);
4482 void R_FrameData_SetMark(void)
4484 if (!r_framedata_mem)
4486 r_framedata_mem->mark = r_framedata_mem->current;
4489 void R_FrameData_ReturnToMark(void)
4491 if (!r_framedata_mem)
4493 r_framedata_mem->current = r_framedata_mem->mark;
4496 //==================================================================================
4498 // LordHavoc: animcache originally written by Echon, rewritten since then
4501 * Animation cache prevents re-generating mesh data for an animated model
4502 * multiple times in one frame for lighting, shadowing, reflections, etc.
4505 void R_AnimCache_Free(void)
4509 void R_AnimCache_ClearCache(void)
4512 entity_render_t *ent;
4514 for (i = 0;i < r_refdef.scene.numentities;i++)
4516 ent = r_refdef.scene.entities[i];
4517 ent->animcache_vertex3f = NULL;
4518 ent->animcache_normal3f = NULL;
4519 ent->animcache_svector3f = NULL;
4520 ent->animcache_tvector3f = NULL;
4521 ent->animcache_vertexmesh = NULL;
4522 ent->animcache_vertex3fbuffer = NULL;
4523 ent->animcache_vertexmeshbuffer = NULL;
4527 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4531 // check if we need the meshbuffers
4532 if (!vid.useinterleavedarrays)
4535 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4536 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4537 // TODO: upload vertex3f buffer?
4538 if (ent->animcache_vertexmesh)
4540 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4541 for (i = 0;i < numvertices;i++)
4542 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4543 if (ent->animcache_svector3f)
4544 for (i = 0;i < numvertices;i++)
4545 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4546 if (ent->animcache_tvector3f)
4547 for (i = 0;i < numvertices;i++)
4548 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4549 if (ent->animcache_normal3f)
4550 for (i = 0;i < numvertices;i++)
4551 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4552 // TODO: upload vertexmeshbuffer?
4556 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4558 dp_model_t *model = ent->model;
4560 // see if it's already cached this frame
4561 if (ent->animcache_vertex3f)
4563 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4564 if (wantnormals || wanttangents)
4566 if (ent->animcache_normal3f)
4567 wantnormals = false;
4568 if (ent->animcache_svector3f)
4569 wanttangents = false;
4570 if (wantnormals || wanttangents)
4572 numvertices = model->surfmesh.num_vertices;
4574 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4577 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4578 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4580 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4581 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4587 // see if this ent is worth caching
4588 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4590 // get some memory for this entity and generate mesh data
4591 numvertices = model->surfmesh.num_vertices;
4592 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4594 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4597 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4598 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4600 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4601 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4606 void R_AnimCache_CacheVisibleEntities(void)
4609 qboolean wantnormals = true;
4610 qboolean wanttangents = !r_showsurfaces.integer;
4612 switch(vid.renderpath)
4614 case RENDERPATH_GL20:
4615 case RENDERPATH_D3D9:
4616 case RENDERPATH_D3D10:
4617 case RENDERPATH_D3D11:
4618 case RENDERPATH_GLES2:
4620 case RENDERPATH_GL11:
4621 case RENDERPATH_GL13:
4622 case RENDERPATH_GLES1:
4623 wanttangents = false;
4625 case RENDERPATH_SOFT:
4629 if (r_shownormals.integer)
4630 wanttangents = wantnormals = true;
4632 // TODO: thread this
4633 // NOTE: R_PrepareRTLights() also caches entities
4635 for (i = 0;i < r_refdef.scene.numentities;i++)
4636 if (r_refdef.viewcache.entityvisible[i])
4637 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4640 //==================================================================================
4642 extern cvar_t r_overheadsprites_pushback;
4644 static void R_View_UpdateEntityLighting (void)
4647 entity_render_t *ent;
4648 vec3_t tempdiffusenormal, avg;
4649 vec_t f, fa, fd, fdd;
4650 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4652 for (i = 0;i < r_refdef.scene.numentities;i++)
4654 ent = r_refdef.scene.entities[i];
4656 // skip unseen models
4657 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4661 if (ent->model && ent->model->brush.num_leafs)
4663 // TODO: use modellight for r_ambient settings on world?
4664 VectorSet(ent->modellight_ambient, 0, 0, 0);
4665 VectorSet(ent->modellight_diffuse, 0, 0, 0);
4666 VectorSet(ent->modellight_lightdir, 0, 0, 1);
4670 // fetch the lighting from the worldmodel data
4671 VectorClear(ent->modellight_ambient);
4672 VectorClear(ent->modellight_diffuse);
4673 VectorClear(tempdiffusenormal);
4674 if (ent->flags & RENDER_LIGHT)
4677 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4679 // complete lightning for lit sprites
4680 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4681 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4683 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4684 org[2] = org[2] + r_overheadsprites_pushback.value;
4685 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4688 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4690 if(ent->flags & RENDER_EQUALIZE)
4692 // first fix up ambient lighting...
4693 if(r_equalize_entities_minambient.value > 0)
4695 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4698 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4699 if(fa < r_equalize_entities_minambient.value * fd)
4702 // fa'/fd' = minambient
4703 // fa'+0.25*fd' = fa+0.25*fd
4705 // fa' = fd' * minambient
4706 // fd'*(0.25+minambient) = fa+0.25*fd
4708 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4709 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4711 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4712 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
4713 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4714 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4719 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4721 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4722 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4726 // adjust brightness and saturation to target
4727 avg[0] = avg[1] = avg[2] = fa / f;
4728 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4729 avg[0] = avg[1] = avg[2] = fd / f;
4730 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4736 VectorSet(ent->modellight_ambient, 1, 1, 1);
4738 // move the light direction into modelspace coordinates for lighting code
4739 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4740 if(VectorLength2(ent->modellight_lightdir) == 0)
4741 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4742 VectorNormalize(ent->modellight_lightdir);
4746 #define MAX_LINEOFSIGHTTRACES 64
4748 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4751 vec3_t boxmins, boxmaxs;
4754 dp_model_t *model = r_refdef.scene.worldmodel;
4756 if (!model || !model->brush.TraceLineOfSight)
4759 // expand the box a little
4760 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4761 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4762 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4763 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4764 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4765 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4767 // return true if eye is inside enlarged box
4768 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4772 VectorCopy(eye, start);
4773 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4774 if (model->brush.TraceLineOfSight(model, start, end))
4777 // try various random positions
4778 for (i = 0;i < numsamples;i++)
4780 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4781 if (model->brush.TraceLineOfSight(model, start, end))
4789 static void R_View_UpdateEntityVisible (void)
4794 entity_render_t *ent;
4796 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4797 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4798 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
4799 : RENDER_EXTERIORMODEL;
4800 if (!r_drawviewmodel.integer)
4801 renderimask |= RENDER_VIEWMODEL;
4802 if (!r_drawexteriormodel.integer)
4803 renderimask |= RENDER_EXTERIORMODEL;
4804 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4806 // worldmodel can check visibility
4807 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4808 for (i = 0;i < r_refdef.scene.numentities;i++)
4810 ent = r_refdef.scene.entities[i];
4811 if (!(ent->flags & renderimask))
4812 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)))
4813 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))
4814 r_refdef.viewcache.entityvisible[i] = true;
4819 // no worldmodel or it can't check visibility
4820 for (i = 0;i < r_refdef.scene.numentities;i++)
4822 ent = r_refdef.scene.entities[i];
4823 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));
4826 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
4827 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4829 for (i = 0;i < r_refdef.scene.numentities;i++)
4831 if (!r_refdef.viewcache.entityvisible[i])
4833 ent = r_refdef.scene.entities[i];
4834 if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4836 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4838 continue; // temp entities do pvs only
4839 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4840 ent->last_trace_visibility = realtime;
4841 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4842 r_refdef.viewcache.entityvisible[i] = 0;
4848 /// only used if skyrendermasked, and normally returns false
4849 int R_DrawBrushModelsSky (void)
4852 entity_render_t *ent;
4855 for (i = 0;i < r_refdef.scene.numentities;i++)
4857 if (!r_refdef.viewcache.entityvisible[i])
4859 ent = r_refdef.scene.entities[i];
4860 if (!ent->model || !ent->model->DrawSky)
4862 ent->model->DrawSky(ent);
4868 static void R_DrawNoModel(entity_render_t *ent);
4869 static void R_DrawModels(void)
4872 entity_render_t *ent;
4874 for (i = 0;i < r_refdef.scene.numentities;i++)
4876 if (!r_refdef.viewcache.entityvisible[i])
4878 ent = r_refdef.scene.entities[i];
4879 r_refdef.stats.entities++;
4881 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
4884 Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
4885 Con_Printf("R_DrawModels\n");
4886 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]);
4887 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);
4888 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);
4891 if (ent->model && ent->model->Draw != NULL)
4892 ent->model->Draw(ent);
4898 static void R_DrawModelsDepth(void)
4901 entity_render_t *ent;
4903 for (i = 0;i < r_refdef.scene.numentities;i++)
4905 if (!r_refdef.viewcache.entityvisible[i])
4907 ent = r_refdef.scene.entities[i];
4908 if (ent->model && ent->model->DrawDepth != NULL)
4909 ent->model->DrawDepth(ent);
4913 static void R_DrawModelsDebug(void)
4916 entity_render_t *ent;
4918 for (i = 0;i < r_refdef.scene.numentities;i++)
4920 if (!r_refdef.viewcache.entityvisible[i])
4922 ent = r_refdef.scene.entities[i];
4923 if (ent->model && ent->model->DrawDebug != NULL)
4924 ent->model->DrawDebug(ent);
4928 static void R_DrawModelsAddWaterPlanes(void)
4931 entity_render_t *ent;
4933 for (i = 0;i < r_refdef.scene.numentities;i++)
4935 if (!r_refdef.viewcache.entityvisible[i])
4937 ent = r_refdef.scene.entities[i];
4938 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4939 ent->model->DrawAddWaterPlanes(ent);
4943 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4945 if (r_hdr_irisadaptation.integer)
4949 vec3_t diffusenormal;
4954 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4955 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
4956 brightness = max(0.0000001f, brightness);
4957 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4958 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4959 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
4960 current = r_hdr_irisadaptation_value.value;
4962 current = min(current + adjust, goal);
4963 else if (current > goal)
4964 current = max(current - adjust, goal);
4965 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4966 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4968 else if (r_hdr_irisadaptation_value.value != 1.0f)
4969 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4972 static void R_View_SetFrustum(const int *scissor)
4975 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
4976 vec3_t forward, left, up, origin, v;
4980 // flipped x coordinates (because x points left here)
4981 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4982 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4984 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
4985 switch(vid.renderpath)
4987 case RENDERPATH_D3D9:
4988 case RENDERPATH_D3D10:
4989 case RENDERPATH_D3D11:
4990 // non-flipped y coordinates
4991 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4992 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4994 case RENDERPATH_SOFT:
4995 case RENDERPATH_GL11:
4996 case RENDERPATH_GL13:
4997 case RENDERPATH_GL20:
4998 case RENDERPATH_GLES1:
4999 case RENDERPATH_GLES2:
5000 // non-flipped y coordinates
5001 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5002 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5007 // we can't trust r_refdef.view.forward and friends in reflected scenes
5008 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5011 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5012 r_refdef.view.frustum[0].normal[1] = 0 - 0;
5013 r_refdef.view.frustum[0].normal[2] = -1 - 0;
5014 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5015 r_refdef.view.frustum[1].normal[1] = 0 + 0;
5016 r_refdef.view.frustum[1].normal[2] = -1 + 0;
5017 r_refdef.view.frustum[2].normal[0] = 0 - 0;
5018 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5019 r_refdef.view.frustum[2].normal[2] = -1 - 0;
5020 r_refdef.view.frustum[3].normal[0] = 0 + 0;
5021 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5022 r_refdef.view.frustum[3].normal[2] = -1 + 0;
5026 zNear = r_refdef.nearclip;
5027 nudge = 1.0 - 1.0 / (1<<23);
5028 r_refdef.view.frustum[4].normal[0] = 0 - 0;
5029 r_refdef.view.frustum[4].normal[1] = 0 - 0;
5030 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5031 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5032 r_refdef.view.frustum[5].normal[0] = 0 + 0;
5033 r_refdef.view.frustum[5].normal[1] = 0 + 0;
5034 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5035 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5041 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5042 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5043 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5044 r_refdef.view.frustum[0].dist = m[15] - m[12];
5046 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5047 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5048 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5049 r_refdef.view.frustum[1].dist = m[15] + m[12];
5051 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5052 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5053 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5054 r_refdef.view.frustum[2].dist = m[15] - m[13];
5056 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5057 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5058 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5059 r_refdef.view.frustum[3].dist = m[15] + m[13];
5061 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5062 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5063 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5064 r_refdef.view.frustum[4].dist = m[15] - m[14];
5066 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5067 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5068 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5069 r_refdef.view.frustum[5].dist = m[15] + m[14];
5072 if (r_refdef.view.useperspective)
5074 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5075 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]);
5076 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]);
5077 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]);
5078 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]);
5080 // then the normals from the corners relative to origin
5081 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5082 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5083 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5084 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5086 // in a NORMAL view, forward cross left == up
5087 // in a REFLECTED view, forward cross left == down
5088 // so our cross products above need to be adjusted for a left handed coordinate system
5089 CrossProduct(forward, left, v);
5090 if(DotProduct(v, up) < 0)
5092 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5093 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5094 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5095 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5098 // Leaving those out was a mistake, those were in the old code, and they
5099 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5100 // I couldn't reproduce it after adding those normalizations. --blub
5101 VectorNormalize(r_refdef.view.frustum[0].normal);
5102 VectorNormalize(r_refdef.view.frustum[1].normal);
5103 VectorNormalize(r_refdef.view.frustum[2].normal);
5104 VectorNormalize(r_refdef.view.frustum[3].normal);
5106 // make the corners absolute
5107 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5108 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5109 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5110 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5113 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5115 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5116 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5117 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5118 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5119 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5123 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5124 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5125 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5126 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5127 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5128 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5129 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5130 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5131 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5132 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5134 r_refdef.view.numfrustumplanes = 5;
5136 if (r_refdef.view.useclipplane)
5138 r_refdef.view.numfrustumplanes = 6;
5139 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5142 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5143 PlaneClassify(r_refdef.view.frustum + i);
5145 // LordHavoc: note to all quake engine coders, Quake had a special case
5146 // for 90 degrees which assumed a square view (wrong), so I removed it,
5147 // Quake2 has it disabled as well.
5149 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5150 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5151 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5152 //PlaneClassify(&frustum[0]);
5154 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5155 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5156 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5157 //PlaneClassify(&frustum[1]);
5159 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5160 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5161 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5162 //PlaneClassify(&frustum[2]);
5164 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5165 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5166 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5167 //PlaneClassify(&frustum[3]);
5170 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5171 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5172 //PlaneClassify(&frustum[4]);
5175 void R_View_UpdateWithScissor(const int *myscissor)
5177 R_Main_ResizeViewCache();
5178 R_View_SetFrustum(myscissor);
5179 R_View_WorldVisibility(r_refdef.view.useclipplane);
5180 R_View_UpdateEntityVisible();
5181 R_View_UpdateEntityLighting();
5184 void R_View_Update(void)
5186 R_Main_ResizeViewCache();
5187 R_View_SetFrustum(NULL);
5188 R_View_WorldVisibility(r_refdef.view.useclipplane);
5189 R_View_UpdateEntityVisible();
5190 R_View_UpdateEntityLighting();
5193 float viewscalefpsadjusted = 1.0f;
5195 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5197 float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5198 scale = bound(0.03125f, scale, 1.0f);
5199 *outwidth = (int)ceil(width * scale);
5200 *outheight = (int)ceil(height * scale);
5203 void R_Mesh_SetMainRenderTargets(void)
5205 if (r_bloomstate.fbo_framebuffer)
5206 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5208 R_Mesh_ResetRenderTargets();
5211 void R_SetupView(qboolean allowwaterclippingplane)
5213 const float *customclipplane = NULL;
5215 int scaledwidth, scaledheight;
5216 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5218 // LordHavoc: couldn't figure out how to make this approach the
5219 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5220 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5221 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5222 dist = r_refdef.view.clipplane.dist;
5223 plane[0] = r_refdef.view.clipplane.normal[0];
5224 plane[1] = r_refdef.view.clipplane.normal[1];
5225 plane[2] = r_refdef.view.clipplane.normal[2];
5227 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5230 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5231 if (!r_refdef.view.useperspective)
5232 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);
5233 else if (vid.stencil && r_useinfinitefarclip.integer)
5234 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);
5236 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);
5237 R_Mesh_SetMainRenderTargets();
5238 R_SetViewport(&r_refdef.view.viewport);
5239 if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5241 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5242 float screenplane[4];
5243 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5244 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5245 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5246 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5247 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5251 void R_EntityMatrix(const matrix4x4_t *matrix)
5253 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5255 gl_modelmatrixchanged = false;
5256 gl_modelmatrix = *matrix;
5257 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5258 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5259 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5260 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5262 switch(vid.renderpath)
5264 case RENDERPATH_D3D9:
5266 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5267 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5270 case RENDERPATH_D3D10:
5271 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5273 case RENDERPATH_D3D11:
5274 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5276 case RENDERPATH_GL11:
5277 case RENDERPATH_GL13:
5278 case RENDERPATH_GLES1:
5279 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5281 case RENDERPATH_SOFT:
5282 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5283 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5285 case RENDERPATH_GL20:
5286 case RENDERPATH_GLES2:
5287 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5288 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5294 void R_ResetViewRendering2D(void)
5296 r_viewport_t viewport;
5299 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5300 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);
5301 R_Mesh_ResetRenderTargets();
5302 R_SetViewport(&viewport);
5303 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5304 GL_Color(1, 1, 1, 1);
5305 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5306 GL_BlendFunc(GL_ONE, GL_ZERO);
5307 GL_ScissorTest(false);
5308 GL_DepthMask(false);
5309 GL_DepthRange(0, 1);
5310 GL_DepthTest(false);
5311 GL_DepthFunc(GL_LEQUAL);
5312 R_EntityMatrix(&identitymatrix);
5313 R_Mesh_ResetTextureState();
5314 GL_PolygonOffset(0, 0);
5315 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5316 switch(vid.renderpath)
5318 case RENDERPATH_GL11:
5319 case RENDERPATH_GL13:
5320 case RENDERPATH_GL20:
5321 case RENDERPATH_GLES1:
5322 case RENDERPATH_GLES2:
5323 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5325 case RENDERPATH_D3D9:
5326 case RENDERPATH_D3D10:
5327 case RENDERPATH_D3D11:
5328 case RENDERPATH_SOFT:
5331 GL_CullFace(GL_NONE);
5334 void R_ResetViewRendering3D(void)
5339 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5340 GL_Color(1, 1, 1, 1);
5341 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5342 GL_BlendFunc(GL_ONE, GL_ZERO);
5343 GL_ScissorTest(true);
5345 GL_DepthRange(0, 1);
5347 GL_DepthFunc(GL_LEQUAL);
5348 R_EntityMatrix(&identitymatrix);
5349 R_Mesh_ResetTextureState();
5350 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5351 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5352 switch(vid.renderpath)
5354 case RENDERPATH_GL11:
5355 case RENDERPATH_GL13:
5356 case RENDERPATH_GL20:
5357 case RENDERPATH_GLES1:
5358 case RENDERPATH_GLES2:
5359 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5361 case RENDERPATH_D3D9:
5362 case RENDERPATH_D3D10:
5363 case RENDERPATH_D3D11:
5364 case RENDERPATH_SOFT:
5367 GL_CullFace(r_refdef.view.cullface_back);
5372 R_RenderView_UpdateViewVectors
5375 static void R_RenderView_UpdateViewVectors(void)
5377 // break apart the view matrix into vectors for various purposes
5378 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5379 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5380 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5381 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5382 // make an inverted copy of the view matrix for tracking sprites
5383 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5386 void R_RenderScene(void);
5387 void R_RenderWaterPlanes(void);
5389 static void R_Water_StartFrame(void)
5392 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5393 r_waterstate_waterplane_t *p;
5395 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5398 switch(vid.renderpath)
5400 case RENDERPATH_GL20:
5401 case RENDERPATH_D3D9:
5402 case RENDERPATH_D3D10:
5403 case RENDERPATH_D3D11:
5404 case RENDERPATH_SOFT:
5405 case RENDERPATH_GLES2:
5407 case RENDERPATH_GL11:
5408 case RENDERPATH_GL13:
5409 case RENDERPATH_GLES1:
5413 // set waterwidth and waterheight to the water resolution that will be
5414 // used (often less than the screen resolution for faster rendering)
5415 R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5417 // calculate desired texture sizes
5418 // can't use water if the card does not support the texture size
5419 if (!r_water.integer || r_showsurfaces.integer)
5420 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5421 else if (vid.support.arb_texture_non_power_of_two)
5423 texturewidth = waterwidth;
5424 textureheight = waterheight;
5425 camerawidth = waterwidth;
5426 cameraheight = waterheight;
5430 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5431 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5432 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
5433 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
5436 // allocate textures as needed
5437 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5439 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5440 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5442 if (p->texture_refraction)
5443 R_FreeTexture(p->texture_refraction);
5444 p->texture_refraction = NULL;
5445 if (p->texture_reflection)
5446 R_FreeTexture(p->texture_reflection);
5447 p->texture_reflection = NULL;
5448 if (p->texture_camera)
5449 R_FreeTexture(p->texture_camera);
5450 p->texture_camera = NULL;
5452 memset(&r_waterstate, 0, sizeof(r_waterstate));
5453 r_waterstate.texturewidth = texturewidth;
5454 r_waterstate.textureheight = textureheight;
5455 r_waterstate.camerawidth = camerawidth;
5456 r_waterstate.cameraheight = cameraheight;
5459 if (r_waterstate.texturewidth)
5461 int scaledwidth, scaledheight;
5463 r_waterstate.enabled = true;
5465 // when doing a reduced render (HDR) we want to use a smaller area
5466 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5467 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5468 R_GetScaledViewSize(r_waterstate.waterwidth, r_waterstate.waterheight, &scaledwidth, &scaledheight);
5470 // set up variables that will be used in shader setup
5471 r_waterstate.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5472 r_waterstate.screenscale[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5473 r_waterstate.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5474 r_waterstate.screencenter[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5477 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5478 r_waterstate.numwaterplanes = 0;
5481 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5483 int triangleindex, planeindex;
5489 r_waterstate_waterplane_t *p;
5490 texture_t *t = R_GetCurrentTexture(surface->texture);
5492 // just use the first triangle with a valid normal for any decisions
5493 VectorClear(normal);
5494 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5496 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5497 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5498 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5499 TriangleNormal(vert[0], vert[1], vert[2], normal);
5500 if (VectorLength2(normal) >= 0.001)
5504 VectorCopy(normal, plane.normal);
5505 VectorNormalize(plane.normal);
5506 plane.dist = DotProduct(vert[0], plane.normal);
5507 PlaneClassify(&plane);
5508 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5510 // skip backfaces (except if nocullface is set)
5511 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5513 VectorNegate(plane.normal, plane.normal);
5515 PlaneClassify(&plane);
5519 // find a matching plane if there is one
5520 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5521 if(p->camera_entity == t->camera_entity)
5522 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5524 if (planeindex >= r_waterstate.maxwaterplanes)
5525 return; // nothing we can do, out of planes
5527 // if this triangle does not fit any known plane rendered this frame, add one
5528 if (planeindex >= r_waterstate.numwaterplanes)
5530 // store the new plane
5531 r_waterstate.numwaterplanes++;
5533 // clear materialflags and pvs
5534 p->materialflags = 0;
5535 p->pvsvalid = false;
5536 p->camera_entity = t->camera_entity;
5537 VectorCopy(surface->mins, p->mins);
5538 VectorCopy(surface->maxs, p->maxs);
5543 p->mins[0] = min(p->mins[0], surface->mins[0]);
5544 p->mins[1] = min(p->mins[1], surface->mins[1]);
5545 p->mins[2] = min(p->mins[2], surface->mins[2]);
5546 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5547 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5548 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5550 // merge this surface's materialflags into the waterplane
5551 p->materialflags |= t->currentmaterialflags;
5552 if(!(p->materialflags & MATERIALFLAG_CAMERA))
5554 // merge this surface's PVS into the waterplane
5555 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5556 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5557 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5559 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5565 extern cvar_t r_drawparticles;
5566 extern cvar_t r_drawdecals;
5568 static void R_Water_ProcessPlanes(void)
5571 r_refdef_view_t originalview;
5572 r_refdef_view_t myview;
5573 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;
5574 r_waterstate_waterplane_t *p;
5577 originalview = r_refdef.view;
5579 // lowquality hack, temporarily shut down some cvars and restore afterwards
5580 qualityreduction = r_water_lowquality.integer;
5581 if (qualityreduction > 0)
5583 if (qualityreduction >= 1)
5585 old_r_shadows = r_shadows.integer;
5586 old_r_worldrtlight = r_shadow_realtime_world.integer;
5587 old_r_dlight = r_shadow_realtime_dlight.integer;
5588 Cvar_SetValueQuick(&r_shadows, 0);
5589 Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5590 Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5592 if (qualityreduction >= 2)
5594 old_r_dynamic = r_dynamic.integer;
5595 old_r_particles = r_drawparticles.integer;
5596 old_r_decals = r_drawdecals.integer;
5597 Cvar_SetValueQuick(&r_dynamic, 0);
5598 Cvar_SetValueQuick(&r_drawparticles, 0);
5599 Cvar_SetValueQuick(&r_drawdecals, 0);
5603 // make sure enough textures are allocated
5604 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5606 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5608 if (!p->texture_refraction)
5609 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);
5610 if (!p->texture_refraction)
5613 else if (p->materialflags & MATERIALFLAG_CAMERA)
5615 if (!p->texture_camera)
5616 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);
5617 if (!p->texture_camera)
5621 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5623 if (!p->texture_reflection)
5624 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);
5625 if (!p->texture_reflection)
5631 r_refdef.view = originalview;
5632 r_refdef.view.showdebug = false;
5633 r_refdef.view.width = r_waterstate.waterwidth;
5634 r_refdef.view.height = r_waterstate.waterheight;
5635 r_refdef.view.useclipplane = true;
5636 myview = r_refdef.view;
5637 r_waterstate.renderingscene = true;
5638 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5640 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5642 r_refdef.view = myview;
5643 if(r_water_scissormode.integer)
5646 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5647 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5650 // render reflected scene and copy into texture
5651 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5652 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5653 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5654 r_refdef.view.clipplane = p->plane;
5655 // reverse the cullface settings for this render
5656 r_refdef.view.cullface_front = GL_FRONT;
5657 r_refdef.view.cullface_back = GL_BACK;
5658 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5660 r_refdef.view.usecustompvs = true;
5662 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5664 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5667 R_ResetViewRendering3D();
5668 R_ClearScreen(r_refdef.fogenabled);
5669 if(r_water_scissormode.integer & 2)
5670 R_View_UpdateWithScissor(myscissor);
5673 if(r_water_scissormode.integer & 1)
5674 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5677 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);
5680 // render the normal view scene and copy into texture
5681 // (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)
5682 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5684 r_refdef.view = myview;
5685 if(r_water_scissormode.integer)
5688 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5689 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5692 r_waterstate.renderingrefraction = true;
5694 r_refdef.view.clipplane = p->plane;
5695 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5696 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5698 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5700 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5701 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5702 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5703 R_RenderView_UpdateViewVectors();
5704 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5706 r_refdef.view.usecustompvs = true;
5707 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);
5711 PlaneClassify(&r_refdef.view.clipplane);
5713 R_ResetViewRendering3D();
5714 R_ClearScreen(r_refdef.fogenabled);
5715 if(r_water_scissormode.integer & 2)
5716 R_View_UpdateWithScissor(myscissor);
5719 if(r_water_scissormode.integer & 1)
5720 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5723 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);
5724 r_waterstate.renderingrefraction = false;
5726 else if (p->materialflags & MATERIALFLAG_CAMERA)
5728 r_refdef.view = myview;
5730 r_refdef.view.clipplane = p->plane;
5731 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5732 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5734 r_refdef.view.width = r_waterstate.camerawidth;
5735 r_refdef.view.height = r_waterstate.cameraheight;
5736 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5737 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5739 if(p->camera_entity)
5741 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5742 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5745 // note: all of the view is used for displaying... so
5746 // there is no use in scissoring
5748 // reverse the cullface settings for this render
5749 r_refdef.view.cullface_front = GL_FRONT;
5750 r_refdef.view.cullface_back = GL_BACK;
5751 // also reverse the view matrix
5752 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
5753 R_RenderView_UpdateViewVectors();
5754 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5756 r_refdef.view.usecustompvs = true;
5757 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);
5760 // camera needs no clipplane
5761 r_refdef.view.useclipplane = false;
5763 PlaneClassify(&r_refdef.view.clipplane);
5765 R_ResetViewRendering3D();
5766 R_ClearScreen(r_refdef.fogenabled);
5770 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);
5771 r_waterstate.renderingrefraction = false;
5775 if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5776 r_waterstate.renderingscene = false;
5777 r_refdef.view = originalview;
5778 R_ResetViewRendering3D();
5779 R_ClearScreen(r_refdef.fogenabled);
5783 r_refdef.view = originalview;
5784 r_waterstate.renderingscene = false;
5785 Cvar_SetValueQuick(&r_water, 0);
5786 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
5788 // lowquality hack, restore cvars
5789 if (qualityreduction > 0)
5791 if (qualityreduction >= 1)
5793 Cvar_SetValueQuick(&r_shadows, old_r_shadows);
5794 Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
5795 Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
5797 if (qualityreduction >= 2)
5799 Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
5800 Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
5801 Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
5806 void R_Bloom_StartFrame(void)
5808 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5809 int viewwidth, viewheight;
5812 if (r_viewscale_fpsscaling.integer)
5814 double actualframetime;
5815 double targetframetime;
5817 actualframetime = r_refdef.lastdrawscreentime;
5818 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5819 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5820 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5821 if (r_viewscale_fpsscaling_stepsize.value > 0)
5822 adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5823 viewscalefpsadjusted += adjust;
5824 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5827 viewscalefpsadjusted = 1.0f;
5829 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5831 switch(vid.renderpath)
5833 case RENDERPATH_GL20:
5834 case RENDERPATH_D3D9:
5835 case RENDERPATH_D3D10:
5836 case RENDERPATH_D3D11:
5837 case RENDERPATH_SOFT:
5838 case RENDERPATH_GLES2:
5840 case RENDERPATH_GL11:
5841 case RENDERPATH_GL13:
5842 case RENDERPATH_GLES1:
5846 // set bloomwidth and bloomheight to the bloom resolution that will be
5847 // used (often less than the screen resolution for faster rendering)
5848 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5849 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5850 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5851 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5852 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5854 // calculate desired texture sizes
5855 if (vid.support.arb_texture_non_power_of_two)
5857 screentexturewidth = vid.width;
5858 screentextureheight = vid.height;
5859 bloomtexturewidth = r_bloomstate.bloomwidth;
5860 bloomtextureheight = r_bloomstate.bloomheight;
5864 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
5865 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
5866 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
5867 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
5870 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))
5872 Cvar_SetValueQuick(&r_hdr, 0);
5873 Cvar_SetValueQuick(&r_bloom, 0);
5874 Cvar_SetValueQuick(&r_motionblur, 0);
5875 Cvar_SetValueQuick(&r_damageblur, 0);
5878 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)
5879 screentexturewidth = screentextureheight = 0;
5880 if (!r_hdr.integer && !r_bloom.integer)
5881 bloomtexturewidth = bloomtextureheight = 0;
5883 textype = TEXTYPE_COLORBUFFER;
5884 switch (vid.renderpath)
5886 case RENDERPATH_GL20:
5887 case RENDERPATH_GLES2:
5888 if (vid.support.ext_framebuffer_object)
5890 if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5891 if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5894 case RENDERPATH_GL11:
5895 case RENDERPATH_GL13:
5896 case RENDERPATH_GLES1:
5897 case RENDERPATH_D3D9:
5898 case RENDERPATH_D3D10:
5899 case RENDERPATH_D3D11:
5900 case RENDERPATH_SOFT:
5904 // allocate textures as needed
5905 if (r_bloomstate.screentexturewidth != screentexturewidth
5906 || r_bloomstate.screentextureheight != screentextureheight
5907 || r_bloomstate.bloomtexturewidth != bloomtexturewidth
5908 || r_bloomstate.bloomtextureheight != bloomtextureheight
5909 || r_bloomstate.texturetype != textype
5910 || r_bloomstate.viewfbo != r_viewfbo.integer)
5912 if (r_bloomstate.texture_bloom)
5913 R_FreeTexture(r_bloomstate.texture_bloom);
5914 r_bloomstate.texture_bloom = NULL;
5915 if (r_bloomstate.texture_screen)
5916 R_FreeTexture(r_bloomstate.texture_screen);
5917 r_bloomstate.texture_screen = NULL;
5918 if (r_bloomstate.fbo_framebuffer)
5919 R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
5920 r_bloomstate.fbo_framebuffer = 0;
5921 if (r_bloomstate.texture_framebuffercolor)
5922 R_FreeTexture(r_bloomstate.texture_framebuffercolor);
5923 r_bloomstate.texture_framebuffercolor = NULL;
5924 if (r_bloomstate.texture_framebufferdepth)
5925 R_FreeTexture(r_bloomstate.texture_framebufferdepth);
5926 r_bloomstate.texture_framebufferdepth = NULL;
5927 r_bloomstate.screentexturewidth = screentexturewidth;
5928 r_bloomstate.screentextureheight = screentextureheight;
5929 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5930 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);
5931 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
5933 // FIXME: choose depth bits based on a cvar
5934 r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
5935 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);
5936 r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5937 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5938 // render depth into one texture and normalmap into the other
5942 qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5943 qglReadBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5944 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
5945 if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
5946 Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
5949 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5950 r_bloomstate.bloomtextureheight = bloomtextureheight;
5951 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5952 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);
5953 r_bloomstate.viewfbo = r_viewfbo.integer;
5954 r_bloomstate.texturetype = textype;
5957 // when doing a reduced render (HDR) we want to use a smaller area
5958 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5959 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5960 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5961 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5962 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5964 // set up a texcoord array for the full resolution screen image
5965 // (we have to keep this around to copy back during final render)
5966 r_bloomstate.screentexcoord2f[0] = 0;
5967 r_bloomstate.screentexcoord2f[1] = (float)viewheight / (float)r_bloomstate.screentextureheight;
5968 r_bloomstate.screentexcoord2f[2] = (float)viewwidth / (float)r_bloomstate.screentexturewidth;
5969 r_bloomstate.screentexcoord2f[3] = (float)viewheight / (float)r_bloomstate.screentextureheight;
5970 r_bloomstate.screentexcoord2f[4] = (float)viewwidth / (float)r_bloomstate.screentexturewidth;
5971 r_bloomstate.screentexcoord2f[5] = 0;
5972 r_bloomstate.screentexcoord2f[6] = 0;
5973 r_bloomstate.screentexcoord2f[7] = 0;
5975 // set up a texcoord array for the reduced resolution bloom image
5976 // (which will be additive blended over the screen image)
5977 r_bloomstate.bloomtexcoord2f[0] = 0;
5978 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5979 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5980 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5981 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5982 r_bloomstate.bloomtexcoord2f[5] = 0;
5983 r_bloomstate.bloomtexcoord2f[6] = 0;
5984 r_bloomstate.bloomtexcoord2f[7] = 0;
5986 switch(vid.renderpath)
5988 case RENDERPATH_GL11:
5989 case RENDERPATH_GL13:
5990 case RENDERPATH_GL20:
5991 case RENDERPATH_SOFT:
5992 case RENDERPATH_GLES1:
5993 case RENDERPATH_GLES2:
5995 case RENDERPATH_D3D9:
5996 case RENDERPATH_D3D10:
5997 case RENDERPATH_D3D11:
6000 for (i = 0;i < 4;i++)
6002 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
6003 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
6004 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
6005 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
6011 if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth)
6013 r_bloomstate.enabled = true;
6014 r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer;
6017 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);
6019 if (r_bloomstate.fbo_framebuffer)
6020 r_refdef.view.clear = true;
6023 void R_Bloom_CopyBloomTexture(float colorscale)
6025 r_refdef.stats.bloom++;
6027 // scale down screen texture to the bloom texture size
6029 R_Mesh_SetMainRenderTargets();
6030 R_SetViewport(&r_bloomstate.viewport);
6031 GL_BlendFunc(GL_ONE, GL_ZERO);
6032 GL_Color(colorscale, colorscale, colorscale, 1);
6033 // 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...
6034 switch(vid.renderpath)
6036 case RENDERPATH_GL11:
6037 case RENDERPATH_GL13:
6038 case RENDERPATH_GL20:
6039 case RENDERPATH_GLES1:
6040 case RENDERPATH_GLES2:
6041 case RENDERPATH_SOFT:
6042 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6044 case RENDERPATH_D3D9:
6045 case RENDERPATH_D3D10:
6046 case RENDERPATH_D3D11:
6047 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6050 // TODO: do boxfilter scale-down in shader?
6051 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, true);
6052 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6053 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6055 // we now have a bloom image in the framebuffer
6056 // copy it into the bloom image texture for later processing
6057 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);
6058 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6061 void R_Bloom_CopyHDRTexture(void)
6063 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);
6064 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6067 void R_Bloom_MakeTexture(void)
6070 float xoffset, yoffset, r, brighten;
6072 r_refdef.stats.bloom++;
6074 R_ResetViewRendering2D();
6076 // we have a bloom image in the framebuffer
6078 R_SetViewport(&r_bloomstate.viewport);
6080 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6083 r = bound(0, r_bloom_colorexponent.value / x, 1);
6084 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6086 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
6087 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, true);
6088 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6089 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6091 // copy the vertically blurred bloom view to a texture
6092 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);
6093 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6096 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
6097 brighten = r_bloom_brighten.value;
6098 if (r_bloomstate.hdr)
6099 brighten *= r_hdr_range.value;
6100 brighten = sqrt(brighten);
6102 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6103 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, true);
6105 for (dir = 0;dir < 2;dir++)
6107 // blend on at multiple vertical offsets to achieve a vertical blur
6108 // TODO: do offset blends using GLSL
6109 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6110 GL_BlendFunc(GL_ONE, GL_ZERO);
6111 for (x = -range;x <= range;x++)
6113 if (!dir){xoffset = 0;yoffset = x;}
6114 else {xoffset = x;yoffset = 0;}
6115 xoffset /= (float)r_bloomstate.bloomtexturewidth;
6116 yoffset /= (float)r_bloomstate.bloomtextureheight;
6117 // compute a texcoord array with the specified x and y offset
6118 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
6119 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6120 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6121 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6122 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6123 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
6124 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
6125 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
6126 // this r value looks like a 'dot' particle, fading sharply to
6127 // black at the edges
6128 // (probably not realistic but looks good enough)
6129 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6130 //r = brighten/(range*2+1);
6131 r = brighten / (range * 2 + 1);
6133 r *= (1 - x*x/(float)(range*range));
6134 GL_Color(r, r, r, 1);
6135 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6136 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6137 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6138 GL_BlendFunc(GL_ONE, GL_ONE);
6141 // copy the vertically blurred bloom view to a texture
6142 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);
6143 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6147 void R_HDR_RenderBloomTexture(void)
6149 int oldwidth, oldheight;
6150 float oldcolorscale;
6151 qboolean oldwaterstate;
6153 oldwaterstate = r_waterstate.enabled;
6154 oldcolorscale = r_refdef.view.colorscale;
6155 oldwidth = r_refdef.view.width;
6156 oldheight = r_refdef.view.height;
6157 r_refdef.view.width = r_bloomstate.bloomwidth;
6158 r_refdef.view.height = r_bloomstate.bloomheight;
6160 if(r_hdr.integer < 2)
6161 r_waterstate.enabled = false;
6163 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
6164 // TODO: add exposure compensation features
6165 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6167 r_refdef.view.showdebug = false;
6168 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6170 R_ResetViewRendering3D();
6172 R_ClearScreen(r_refdef.fogenabled);
6173 if (r_timereport_active)
6174 R_TimeReport("HDRclear");
6177 if (r_timereport_active)
6178 R_TimeReport("visibility");
6180 // only do secondary renders with HDR if r_hdr is 2 or higher
6181 r_waterstate.numwaterplanes = 0;
6182 if (r_waterstate.enabled)
6183 R_RenderWaterPlanes();
6185 r_refdef.view.showdebug = true;
6187 r_waterstate.numwaterplanes = 0;
6189 R_ResetViewRendering2D();
6191 R_Bloom_CopyHDRTexture();
6192 R_Bloom_MakeTexture();
6194 // restore the view settings
6195 r_waterstate.enabled = oldwaterstate;
6196 r_refdef.view.width = oldwidth;
6197 r_refdef.view.height = oldheight;
6198 r_refdef.view.colorscale = oldcolorscale;
6200 R_ResetViewRendering3D();
6202 R_ClearScreen(r_refdef.fogenabled);
6203 if (r_timereport_active)
6204 R_TimeReport("viewclear");
6207 static void R_BlendView(void)
6209 unsigned int permutation;
6210 float uservecs[4][4];
6212 switch (vid.renderpath)
6214 case RENDERPATH_GL20:
6215 case RENDERPATH_D3D9:
6216 case RENDERPATH_D3D10:
6217 case RENDERPATH_D3D11:
6218 case RENDERPATH_SOFT:
6219 case RENDERPATH_GLES2:
6221 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6222 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6223 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6224 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6225 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6227 if (r_bloomstate.texture_screen)
6229 // make sure the buffer is available
6230 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6232 R_ResetViewRendering2D();
6233 R_Mesh_SetMainRenderTargets();
6235 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6237 // declare variables
6239 static float avgspeed;
6241 speed = VectorLength(cl.movement_velocity);
6243 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
6244 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
6246 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
6247 speed = bound(0, speed, 1);
6248 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
6250 // calculate values into a standard alpha
6251 cl.motionbluralpha = 1 - exp(-
6253 (r_motionblur.value * speed / 80)
6255 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6258 max(0.0001, cl.time - cl.oldtime) // fps independent
6261 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6262 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6264 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6266 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6267 GL_Color(1, 1, 1, cl.motionbluralpha);
6268 switch(vid.renderpath)
6270 case RENDERPATH_GL11:
6271 case RENDERPATH_GL13:
6272 case RENDERPATH_GL20:
6273 case RENDERPATH_GLES1:
6274 case RENDERPATH_GLES2:
6275 case RENDERPATH_SOFT:
6276 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6278 case RENDERPATH_D3D9:
6279 case RENDERPATH_D3D10:
6280 case RENDERPATH_D3D11:
6281 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6284 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, true);
6285 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6286 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6290 // copy view into the screen texture
6291 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);
6292 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6294 else if (!r_bloomstate.texture_bloom)
6296 // we may still have to do view tint...
6297 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6299 // apply a color tint to the whole view
6300 R_ResetViewRendering2D();
6301 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6302 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6303 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, true);
6304 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6305 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6307 break; // no screen processing, no bloom, skip it
6310 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6312 // render simple bloom effect
6313 // copy the screen and shrink it and darken it for the bloom process
6314 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6315 // make the bloom texture
6316 R_Bloom_MakeTexture();
6319 #if _MSC_VER >= 1400
6320 #define sscanf sscanf_s
6322 memset(uservecs, 0, sizeof(uservecs));
6323 if (r_glsl_postprocess_uservec1_enable.integer)
6324 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6325 if (r_glsl_postprocess_uservec2_enable.integer)
6326 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6327 if (r_glsl_postprocess_uservec3_enable.integer)
6328 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6329 if (r_glsl_postprocess_uservec4_enable.integer)
6330 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6332 R_ResetViewRendering2D();
6333 GL_Color(1, 1, 1, 1);
6334 GL_BlendFunc(GL_ONE, GL_ZERO);
6336 switch(vid.renderpath)
6338 case RENDERPATH_GL20:
6339 case RENDERPATH_GLES2:
6340 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6341 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6342 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_bloomstate.texture_screen);
6343 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_bloomstate.texture_bloom );
6344 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6345 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]);
6346 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6347 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]);
6348 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]);
6349 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]);
6350 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]);
6351 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6352 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6353 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);
6355 case RENDERPATH_D3D9:
6357 // 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...
6358 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6359 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6360 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6361 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6362 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6363 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6364 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6365 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6366 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6367 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6368 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6369 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6370 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6371 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6374 case RENDERPATH_D3D10:
6375 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6377 case RENDERPATH_D3D11:
6378 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6380 case RENDERPATH_SOFT:
6381 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6382 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6383 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6384 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6385 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6386 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6387 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6388 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6389 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6390 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6391 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6392 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6393 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6394 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6399 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6400 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6402 case RENDERPATH_GL11:
6403 case RENDERPATH_GL13:
6404 case RENDERPATH_GLES1:
6405 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6407 // apply a color tint to the whole view
6408 R_ResetViewRendering2D();
6409 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6410 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6411 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, true);
6412 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6413 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6419 matrix4x4_t r_waterscrollmatrix;
6421 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6423 if (r_refdef.fog_density)
6425 r_refdef.fogcolor[0] = r_refdef.fog_red;
6426 r_refdef.fogcolor[1] = r_refdef.fog_green;
6427 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6429 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6430 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6431 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6432 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6436 VectorCopy(r_refdef.fogcolor, fogvec);
6437 // color.rgb *= ContrastBoost * SceneBrightness;
6438 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6439 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6440 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6441 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6446 void R_UpdateVariables(void)
6450 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6452 r_refdef.farclip = r_farclip_base.value;
6453 if (r_refdef.scene.worldmodel)
6454 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6455 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6457 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6458 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6459 r_refdef.polygonfactor = 0;
6460 r_refdef.polygonoffset = 0;
6461 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6462 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6464 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6465 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6466 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6467 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6468 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6469 if (FAKELIGHT_ENABLED)
6471 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6473 if (r_showsurfaces.integer)
6475 r_refdef.scene.rtworld = false;
6476 r_refdef.scene.rtworldshadows = false;
6477 r_refdef.scene.rtdlight = false;
6478 r_refdef.scene.rtdlightshadows = false;
6479 r_refdef.lightmapintensity = 0;
6482 if (gamemode == GAME_NEHAHRA)
6484 if (gl_fogenable.integer)
6486 r_refdef.oldgl_fogenable = true;
6487 r_refdef.fog_density = gl_fogdensity.value;
6488 r_refdef.fog_red = gl_fogred.value;
6489 r_refdef.fog_green = gl_foggreen.value;
6490 r_refdef.fog_blue = gl_fogblue.value;
6491 r_refdef.fog_alpha = 1;
6492 r_refdef.fog_start = 0;
6493 r_refdef.fog_end = gl_skyclip.value;
6494 r_refdef.fog_height = 1<<30;
6495 r_refdef.fog_fadedepth = 128;
6497 else if (r_refdef.oldgl_fogenable)
6499 r_refdef.oldgl_fogenable = false;
6500 r_refdef.fog_density = 0;
6501 r_refdef.fog_red = 0;
6502 r_refdef.fog_green = 0;
6503 r_refdef.fog_blue = 0;
6504 r_refdef.fog_alpha = 0;
6505 r_refdef.fog_start = 0;
6506 r_refdef.fog_end = 0;
6507 r_refdef.fog_height = 1<<30;
6508 r_refdef.fog_fadedepth = 128;
6512 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6513 r_refdef.fog_start = max(0, r_refdef.fog_start);
6514 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6516 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6518 if (r_refdef.fog_density && r_drawfog.integer)
6520 r_refdef.fogenabled = true;
6521 // this is the point where the fog reaches 0.9986 alpha, which we
6522 // consider a good enough cutoff point for the texture
6523 // (0.9986 * 256 == 255.6)
6524 if (r_fog_exp2.integer)
6525 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6527 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6528 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6529 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6530 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6531 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6532 R_BuildFogHeightTexture();
6533 // fog color was already set
6534 // update the fog texture
6535 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)
6536 R_BuildFogTexture();
6537 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6538 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6541 r_refdef.fogenabled = false;
6543 switch(vid.renderpath)
6545 case RENDERPATH_GL20:
6546 case RENDERPATH_D3D9:
6547 case RENDERPATH_D3D10:
6548 case RENDERPATH_D3D11:
6549 case RENDERPATH_SOFT:
6550 case RENDERPATH_GLES2:
6551 if(v_glslgamma.integer && !vid_gammatables_trivial)
6553 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6555 // build GLSL gamma texture
6556 #define RAMPWIDTH 256
6557 unsigned short ramp[RAMPWIDTH * 3];
6558 unsigned char rampbgr[RAMPWIDTH][4];
6561 r_texture_gammaramps_serial = vid_gammatables_serial;
6563 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6564 for(i = 0; i < RAMPWIDTH; ++i)
6566 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6567 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6568 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6571 if (r_texture_gammaramps)
6573 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6577 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6583 // remove GLSL gamma texture
6586 case RENDERPATH_GL11:
6587 case RENDERPATH_GL13:
6588 case RENDERPATH_GLES1:
6593 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6594 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6600 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6601 if( scenetype != r_currentscenetype ) {
6602 // store the old scenetype
6603 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6604 r_currentscenetype = scenetype;
6605 // move in the new scene
6606 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6615 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6617 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6618 if( scenetype == r_currentscenetype ) {
6619 return &r_refdef.scene;
6621 return &r_scenes_store[ scenetype ];
6630 int dpsoftrast_test;
6631 void R_RenderView(void)
6633 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6635 dpsoftrast_test = r_test.integer;
6637 if (r_timereport_active)
6638 R_TimeReport("start");
6639 r_textureframe++; // used only by R_GetCurrentTexture
6640 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6642 if(R_CompileShader_CheckStaticParms())
6645 if (!r_drawentities.integer)
6646 r_refdef.scene.numentities = 0;
6648 R_AnimCache_ClearCache();
6649 R_FrameData_NewFrame();
6651 /* adjust for stereo display */
6652 if(R_Stereo_Active())
6654 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);
6655 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6658 if (r_refdef.view.isoverlay)
6660 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6661 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6662 R_TimeReport("depthclear");
6664 r_refdef.view.showdebug = false;
6666 r_waterstate.enabled = false;
6667 r_waterstate.numwaterplanes = 0;
6671 r_refdef.view.matrix = originalmatrix;
6677 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6679 r_refdef.view.matrix = originalmatrix;
6680 return; //Host_Error ("R_RenderView: NULL worldmodel");
6683 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6685 R_RenderView_UpdateViewVectors();
6687 R_Shadow_UpdateWorldLightSelection();
6689 R_Bloom_StartFrame();
6690 R_Water_StartFrame();
6693 if (r_timereport_active)
6694 R_TimeReport("viewsetup");
6696 R_ResetViewRendering3D();
6698 if (r_refdef.view.clear || r_refdef.fogenabled)
6700 R_ClearScreen(r_refdef.fogenabled);
6701 if (r_timereport_active)
6702 R_TimeReport("viewclear");
6704 r_refdef.view.clear = true;
6706 // this produces a bloom texture to be used in R_BlendView() later
6707 if (r_bloomstate.hdr)
6709 R_HDR_RenderBloomTexture();
6710 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6711 r_textureframe++; // used only by R_GetCurrentTexture
6714 r_refdef.view.showdebug = true;
6717 if (r_timereport_active)
6718 R_TimeReport("visibility");
6720 r_waterstate.numwaterplanes = 0;
6721 if (r_waterstate.enabled)
6722 R_RenderWaterPlanes();
6725 r_waterstate.numwaterplanes = 0;
6728 if (r_timereport_active)
6729 R_TimeReport("blendview");
6731 GL_Scissor(0, 0, vid.width, vid.height);
6732 GL_ScissorTest(false);
6734 r_refdef.view.matrix = originalmatrix;
6739 void R_RenderWaterPlanes(void)
6741 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6743 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6744 if (r_timereport_active)
6745 R_TimeReport("waterworld");
6748 // don't let sound skip if going slow
6749 if (r_refdef.scene.extraupdate)
6752 R_DrawModelsAddWaterPlanes();
6753 if (r_timereport_active)
6754 R_TimeReport("watermodels");
6756 if (r_waterstate.numwaterplanes)
6758 R_Water_ProcessPlanes();
6759 if (r_timereport_active)
6760 R_TimeReport("waterscenes");
6764 extern void R_DrawLightningBeams (void);
6765 extern void VM_CL_AddPolygonsToMeshQueue (void);
6766 extern void R_DrawPortals (void);
6767 extern cvar_t cl_locs_show;
6768 static void R_DrawLocs(void);
6769 static void R_DrawEntityBBoxes(void);
6770 static void R_DrawModelDecals(void);
6771 extern void R_DrawModelShadows(void);
6772 extern void R_DrawModelShadowMaps(void);
6773 extern cvar_t cl_decals_newsystem;
6774 extern qboolean r_shadow_usingdeferredprepass;
6775 void R_RenderScene(void)
6777 qboolean shadowmapping = false;
6779 if (r_timereport_active)
6780 R_TimeReport("beginscene");
6782 r_refdef.stats.renders++;
6786 // don't let sound skip if going slow
6787 if (r_refdef.scene.extraupdate)
6790 R_MeshQueue_BeginScene();
6794 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);
6796 if (r_timereport_active)
6797 R_TimeReport("skystartframe");
6799 if (cl.csqc_vidvars.drawworld)
6801 // don't let sound skip if going slow
6802 if (r_refdef.scene.extraupdate)
6805 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6807 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6808 if (r_timereport_active)
6809 R_TimeReport("worldsky");
6812 if (R_DrawBrushModelsSky() && r_timereport_active)
6813 R_TimeReport("bmodelsky");
6815 if (skyrendermasked && skyrenderlater)
6817 // we have to force off the water clipping plane while rendering sky
6821 if (r_timereport_active)
6822 R_TimeReport("sky");
6826 R_AnimCache_CacheVisibleEntities();
6827 if (r_timereport_active)
6828 R_TimeReport("animation");
6830 R_Shadow_PrepareLights();
6831 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6832 R_Shadow_PrepareModelShadows();
6833 if (r_timereport_active)
6834 R_TimeReport("preparelights");
6836 if (R_Shadow_ShadowMappingEnabled())
6837 shadowmapping = true;
6839 if (r_shadow_usingdeferredprepass)
6840 R_Shadow_DrawPrepass();
6842 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6844 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6845 if (r_timereport_active)
6846 R_TimeReport("worlddepth");
6848 if (r_depthfirst.integer >= 2)
6850 R_DrawModelsDepth();
6851 if (r_timereport_active)
6852 R_TimeReport("modeldepth");
6855 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6857 R_DrawModelShadowMaps();
6858 R_ResetViewRendering3D();
6859 // don't let sound skip if going slow
6860 if (r_refdef.scene.extraupdate)
6864 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6866 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6867 if (r_timereport_active)
6868 R_TimeReport("world");
6871 // don't let sound skip if going slow
6872 if (r_refdef.scene.extraupdate)
6876 if (r_timereport_active)
6877 R_TimeReport("models");
6879 // don't let sound skip if going slow
6880 if (r_refdef.scene.extraupdate)
6883 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6885 R_DrawModelShadows();
6886 R_ResetViewRendering3D();
6887 // don't let sound skip if going slow
6888 if (r_refdef.scene.extraupdate)
6892 if (!r_shadow_usingdeferredprepass)
6894 R_Shadow_DrawLights();
6895 if (r_timereport_active)
6896 R_TimeReport("rtlights");
6899 // don't let sound skip if going slow
6900 if (r_refdef.scene.extraupdate)
6903 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6905 R_DrawModelShadows();
6906 R_ResetViewRendering3D();
6907 // don't let sound skip if going slow
6908 if (r_refdef.scene.extraupdate)
6912 if (cl.csqc_vidvars.drawworld)
6914 if (cl_decals_newsystem.integer)
6916 R_DrawModelDecals();
6917 if (r_timereport_active)
6918 R_TimeReport("modeldecals");
6923 if (r_timereport_active)
6924 R_TimeReport("decals");
6928 if (r_timereport_active)
6929 R_TimeReport("particles");
6932 if (r_timereport_active)
6933 R_TimeReport("explosions");
6935 R_DrawLightningBeams();
6936 if (r_timereport_active)
6937 R_TimeReport("lightning");
6940 VM_CL_AddPolygonsToMeshQueue();
6942 if (r_refdef.view.showdebug)
6944 if (cl_locs_show.integer)
6947 if (r_timereport_active)
6948 R_TimeReport("showlocs");
6951 if (r_drawportals.integer)
6954 if (r_timereport_active)
6955 R_TimeReport("portals");
6958 if (r_showbboxes.value > 0)
6960 R_DrawEntityBBoxes();
6961 if (r_timereport_active)
6962 R_TimeReport("bboxes");
6966 if (r_transparent.integer)
6968 R_MeshQueue_RenderTransparent();
6969 if (r_timereport_active)
6970 R_TimeReport("drawtrans");
6973 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))
6975 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6976 if (r_timereport_active)
6977 R_TimeReport("worlddebug");
6978 R_DrawModelsDebug();
6979 if (r_timereport_active)
6980 R_TimeReport("modeldebug");
6983 if (cl.csqc_vidvars.drawworld)
6985 R_Shadow_DrawCoronas();
6986 if (r_timereport_active)
6987 R_TimeReport("coronas");
6992 GL_DepthTest(false);
6993 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6994 GL_Color(1, 1, 1, 1);
6995 qglBegin(GL_POLYGON);
6996 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6997 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6998 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6999 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7001 qglBegin(GL_POLYGON);
7002 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]);
7003 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]);
7004 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]);
7005 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]);
7007 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7011 // don't let sound skip if going slow
7012 if (r_refdef.scene.extraupdate)
7015 R_ResetViewRendering2D();
7018 static const unsigned short bboxelements[36] =
7028 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7031 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7033 RSurf_ActiveWorldEntity();
7035 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7036 GL_DepthMask(false);
7037 GL_DepthRange(0, 1);
7038 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7039 // R_Mesh_ResetTextureState();
7041 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7042 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7043 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7044 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7045 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7046 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7047 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7048 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7049 R_FillColors(color4f, 8, cr, cg, cb, ca);
7050 if (r_refdef.fogenabled)
7052 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7054 f1 = RSurf_FogVertex(v);
7056 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7057 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7058 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7061 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7062 R_Mesh_ResetTextureState();
7063 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
7064 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7067 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7071 prvm_edict_t *edict;
7072 prvm_prog_t *prog_save = prog;
7074 // this function draws bounding boxes of server entities
7078 GL_CullFace(GL_NONE);
7079 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
7083 for (i = 0;i < numsurfaces;i++)
7085 edict = PRVM_EDICT_NUM(surfacelist[i]);
7086 switch ((int)edict->fields.server->solid)
7088 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
7089 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
7090 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
7091 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7092 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
7093 default: Vector4Set(color, 0, 0, 0, 0.50);break;
7095 color[3] *= r_showbboxes.value;
7096 color[3] = bound(0, color[3], 1);
7097 GL_DepthTest(!r_showdisabledepthtest.integer);
7098 GL_CullFace(r_refdef.view.cullface_front);
7099 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7105 static void R_DrawEntityBBoxes(void)
7108 prvm_edict_t *edict;
7110 prvm_prog_t *prog_save = prog;
7112 // this function draws bounding boxes of server entities
7118 for (i = 0;i < prog->num_edicts;i++)
7120 edict = PRVM_EDICT_NUM(i);
7121 if (edict->priv.server->free)
7123 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7124 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7126 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7128 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7129 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7135 static const int nomodelelement3i[24] =
7147 static const unsigned short nomodelelement3s[24] =
7159 static const float nomodelvertex3f[6*3] =
7169 static const float nomodelcolor4f[6*4] =
7171 0.0f, 0.0f, 0.5f, 1.0f,
7172 0.0f, 0.0f, 0.5f, 1.0f,
7173 0.0f, 0.5f, 0.0f, 1.0f,
7174 0.0f, 0.5f, 0.0f, 1.0f,
7175 0.5f, 0.0f, 0.0f, 1.0f,
7176 0.5f, 0.0f, 0.0f, 1.0f
7179 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7185 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);
7187 // this is only called once per entity so numsurfaces is always 1, and
7188 // surfacelist is always {0}, so this code does not handle batches
7190 if (rsurface.ent_flags & RENDER_ADDITIVE)
7192 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7193 GL_DepthMask(false);
7195 else if (rsurface.colormod[3] < 1)
7197 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7198 GL_DepthMask(false);
7202 GL_BlendFunc(GL_ONE, GL_ZERO);
7205 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7206 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7207 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7208 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7209 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7210 for (i = 0, c = color4f;i < 6;i++, c += 4)
7212 c[0] *= rsurface.colormod[0];
7213 c[1] *= rsurface.colormod[1];
7214 c[2] *= rsurface.colormod[2];
7215 c[3] *= rsurface.colormod[3];
7217 if (r_refdef.fogenabled)
7219 for (i = 0, c = color4f;i < 6;i++, c += 4)
7221 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7223 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7224 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7225 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7228 // R_Mesh_ResetTextureState();
7229 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
7230 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7231 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7234 void R_DrawNoModel(entity_render_t *ent)
7237 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7238 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7239 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7241 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7244 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7246 vec3_t right1, right2, diff, normal;
7248 VectorSubtract (org2, org1, normal);
7250 // calculate 'right' vector for start
7251 VectorSubtract (r_refdef.view.origin, org1, diff);
7252 CrossProduct (normal, diff, right1);
7253 VectorNormalize (right1);
7255 // calculate 'right' vector for end
7256 VectorSubtract (r_refdef.view.origin, org2, diff);
7257 CrossProduct (normal, diff, right2);
7258 VectorNormalize (right2);
7260 vert[ 0] = org1[0] + width * right1[0];
7261 vert[ 1] = org1[1] + width * right1[1];
7262 vert[ 2] = org1[2] + width * right1[2];
7263 vert[ 3] = org1[0] - width * right1[0];
7264 vert[ 4] = org1[1] - width * right1[1];
7265 vert[ 5] = org1[2] - width * right1[2];
7266 vert[ 6] = org2[0] - width * right2[0];
7267 vert[ 7] = org2[1] - width * right2[1];
7268 vert[ 8] = org2[2] - width * right2[2];
7269 vert[ 9] = org2[0] + width * right2[0];
7270 vert[10] = org2[1] + width * right2[1];
7271 vert[11] = org2[2] + width * right2[2];
7274 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)
7276 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7277 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7278 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7279 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7280 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7281 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7282 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7283 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7284 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7285 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7286 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7287 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7290 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7295 VectorSet(v, x, y, z);
7296 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7297 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7299 if (i == mesh->numvertices)
7301 if (mesh->numvertices < mesh->maxvertices)
7303 VectorCopy(v, vertex3f);
7304 mesh->numvertices++;
7306 return mesh->numvertices;
7312 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7316 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7317 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7318 e = mesh->element3i + mesh->numtriangles * 3;
7319 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7321 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7322 if (mesh->numtriangles < mesh->maxtriangles)
7327 mesh->numtriangles++;
7329 element[1] = element[2];
7333 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7337 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7338 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7339 e = mesh->element3i + mesh->numtriangles * 3;
7340 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7342 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7343 if (mesh->numtriangles < mesh->maxtriangles)
7348 mesh->numtriangles++;
7350 element[1] = element[2];
7354 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7355 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7357 int planenum, planenum2;
7360 mplane_t *plane, *plane2;
7362 double temppoints[2][256*3];
7363 // figure out how large a bounding box we need to properly compute this brush
7365 for (w = 0;w < numplanes;w++)
7366 maxdist = max(maxdist, fabs(planes[w].dist));
7367 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7368 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7369 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7373 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7374 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7376 if (planenum2 == planenum)
7378 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);
7381 if (tempnumpoints < 3)
7383 // generate elements forming a triangle fan for this polygon
7384 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7388 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)
7390 texturelayer_t *layer;
7391 layer = t->currentlayers + t->currentnumlayers++;
7393 layer->depthmask = depthmask;
7394 layer->blendfunc1 = blendfunc1;
7395 layer->blendfunc2 = blendfunc2;
7396 layer->texture = texture;
7397 layer->texmatrix = *matrix;
7398 layer->color[0] = r;
7399 layer->color[1] = g;
7400 layer->color[2] = b;
7401 layer->color[3] = a;
7404 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7406 if(parms[0] == 0 && parms[1] == 0)
7408 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7409 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7414 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7417 index = parms[2] + rsurface.shadertime * parms[3];
7418 index -= floor(index);
7419 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7422 case Q3WAVEFUNC_NONE:
7423 case Q3WAVEFUNC_NOISE:
7424 case Q3WAVEFUNC_COUNT:
7427 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7428 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7429 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7430 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7431 case Q3WAVEFUNC_TRIANGLE:
7433 f = index - floor(index);
7444 f = parms[0] + parms[1] * f;
7445 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7446 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7450 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7456 matrix4x4_t matrix, temp;
7457 switch(tcmod->tcmod)
7461 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7462 matrix = r_waterscrollmatrix;
7464 matrix = identitymatrix;
7466 case Q3TCMOD_ENTITYTRANSLATE:
7467 // this is used in Q3 to allow the gamecode to control texcoord
7468 // scrolling on the entity, which is not supported in darkplaces yet.
7469 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7471 case Q3TCMOD_ROTATE:
7472 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7473 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
7474 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7477 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7479 case Q3TCMOD_SCROLL:
7480 // extra care is needed because of precision breakdown with large values of time
7481 offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7482 offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7483 Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7485 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7486 w = (int) tcmod->parms[0];
7487 h = (int) tcmod->parms[1];
7488 f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7490 idx = (int) floor(f * w * h);
7491 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7493 case Q3TCMOD_STRETCH:
7494 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7495 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7497 case Q3TCMOD_TRANSFORM:
7498 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
7499 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
7500 VectorSet(tcmat + 6, 0 , 0 , 1);
7501 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
7502 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7504 case Q3TCMOD_TURBULENT:
7505 // this is handled in the RSurf_PrepareVertices function
7506 matrix = identitymatrix;
7510 Matrix4x4_Concat(texmatrix, &matrix, &temp);
7513 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7515 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7516 char name[MAX_QPATH];
7517 skinframe_t *skinframe;
7518 unsigned char pixels[296*194];
7519 strlcpy(cache->name, skinname, sizeof(cache->name));
7520 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7521 if (developer_loading.integer)
7522 Con_Printf("loading %s\n", name);
7523 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7524 if (!skinframe || !skinframe->base)
7527 fs_offset_t filesize;
7529 f = FS_LoadFile(name, tempmempool, true, &filesize);
7532 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7533 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7537 cache->skinframe = skinframe;
7540 texture_t *R_GetCurrentTexture(texture_t *t)
7543 const entity_render_t *ent = rsurface.entity;
7544 dp_model_t *model = ent->model;
7545 q3shaderinfo_layer_tcmod_t *tcmod;
7547 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7548 return t->currentframe;
7549 t->update_lastrenderframe = r_textureframe;
7550 t->update_lastrenderentity = (void *)ent;
7552 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7553 t->camera_entity = ent->entitynumber;
7555 t->camera_entity = 0;
7557 // switch to an alternate material if this is a q1bsp animated material
7559 texture_t *texture = t;
7560 int s = rsurface.ent_skinnum;
7561 if ((unsigned int)s >= (unsigned int)model->numskins)
7563 if (model->skinscenes)
7565 if (model->skinscenes[s].framecount > 1)
7566 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7568 s = model->skinscenes[s].firstframe;
7571 t = t + s * model->num_surfaces;
7574 // use an alternate animation if the entity's frame is not 0,
7575 // and only if the texture has an alternate animation
7576 if (rsurface.ent_alttextures && t->anim_total[1])
7577 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7579 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7581 texture->currentframe = t;
7584 // update currentskinframe to be a qw skin or animation frame
7585 if (rsurface.ent_qwskin >= 0)
7587 i = rsurface.ent_qwskin;
7588 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7590 r_qwskincache_size = cl.maxclients;
7592 Mem_Free(r_qwskincache);
7593 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7595 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7596 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7597 t->currentskinframe = r_qwskincache[i].skinframe;
7598 if (t->currentskinframe == NULL)
7599 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7601 else if (t->numskinframes >= 2)
7602 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7603 if (t->backgroundnumskinframes >= 2)
7604 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7606 t->currentmaterialflags = t->basematerialflags;
7607 t->currentalpha = rsurface.colormod[3];
7608 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7609 t->currentalpha *= r_wateralpha.value;
7610 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7611 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7612 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7613 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7614 if (!(rsurface.ent_flags & RENDER_LIGHT))
7615 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7616 else if (FAKELIGHT_ENABLED)
7618 // no modellight if using fakelight for the map
7620 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7622 // pick a model lighting mode
7623 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7624 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7626 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7628 if (rsurface.ent_flags & RENDER_ADDITIVE)
7629 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7630 else if (t->currentalpha < 1)
7631 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7632 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7633 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7634 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7635 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7636 if (t->backgroundnumskinframes)
7637 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7638 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7640 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7641 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7644 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7645 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7646 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7648 // there is no tcmod
7649 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7651 t->currenttexmatrix = r_waterscrollmatrix;
7652 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7654 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7656 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7657 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7660 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7661 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7662 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7663 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7665 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7666 if (t->currentskinframe->qpixels)
7667 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7668 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7669 if (!t->basetexture)
7670 t->basetexture = r_texture_notexture;
7671 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7672 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7673 t->nmaptexture = t->currentskinframe->nmap;
7674 if (!t->nmaptexture)
7675 t->nmaptexture = r_texture_blanknormalmap;
7676 t->glosstexture = r_texture_black;
7677 t->glowtexture = t->currentskinframe->glow;
7678 t->fogtexture = t->currentskinframe->fog;
7679 t->reflectmasktexture = t->currentskinframe->reflect;
7680 if (t->backgroundnumskinframes)
7682 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7683 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7684 t->backgroundglosstexture = r_texture_black;
7685 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7686 if (!t->backgroundnmaptexture)
7687 t->backgroundnmaptexture = r_texture_blanknormalmap;
7691 t->backgroundbasetexture = r_texture_white;
7692 t->backgroundnmaptexture = r_texture_blanknormalmap;
7693 t->backgroundglosstexture = r_texture_black;
7694 t->backgroundglowtexture = NULL;
7696 t->specularpower = r_shadow_glossexponent.value;
7697 // TODO: store reference values for these in the texture?
7698 t->specularscale = 0;
7699 if (r_shadow_gloss.integer > 0)
7701 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7703 if (r_shadow_glossintensity.value > 0)
7705 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7706 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7707 t->specularscale = r_shadow_glossintensity.value;
7710 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7712 t->glosstexture = r_texture_white;
7713 t->backgroundglosstexture = r_texture_white;
7714 t->specularscale = r_shadow_gloss2intensity.value;
7715 t->specularpower = r_shadow_gloss2exponent.value;
7718 t->specularscale *= t->specularscalemod;
7719 t->specularpower *= t->specularpowermod;
7721 // lightmaps mode looks bad with dlights using actual texturing, so turn
7722 // off the colormap and glossmap, but leave the normalmap on as it still
7723 // accurately represents the shading involved
7724 if (gl_lightmaps.integer)
7726 t->basetexture = r_texture_grey128;
7727 t->pantstexture = r_texture_black;
7728 t->shirttexture = r_texture_black;
7729 t->nmaptexture = r_texture_blanknormalmap;
7730 t->glosstexture = r_texture_black;
7731 t->glowtexture = NULL;
7732 t->fogtexture = NULL;
7733 t->reflectmasktexture = NULL;
7734 t->backgroundbasetexture = NULL;
7735 t->backgroundnmaptexture = r_texture_blanknormalmap;
7736 t->backgroundglosstexture = r_texture_black;
7737 t->backgroundglowtexture = NULL;
7738 t->specularscale = 0;
7739 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7742 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7743 VectorClear(t->dlightcolor);
7744 t->currentnumlayers = 0;
7745 if (t->currentmaterialflags & MATERIALFLAG_WALL)
7747 int blendfunc1, blendfunc2;
7749 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7751 blendfunc1 = GL_SRC_ALPHA;
7752 blendfunc2 = GL_ONE;
7754 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7756 blendfunc1 = GL_SRC_ALPHA;
7757 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7759 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7761 blendfunc1 = t->customblendfunc[0];
7762 blendfunc2 = t->customblendfunc[1];
7766 blendfunc1 = GL_ONE;
7767 blendfunc2 = GL_ZERO;
7769 // don't colormod evilblend textures
7770 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7771 VectorSet(t->lightmapcolor, 1, 1, 1);
7772 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7773 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7775 // fullbright is not affected by r_refdef.lightmapintensity
7776 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]);
7777 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7778 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]);
7779 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7780 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]);
7784 vec3_t ambientcolor;
7786 // set the color tint used for lights affecting this surface
7787 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7789 // q3bsp has no lightmap updates, so the lightstylevalue that
7790 // would normally be baked into the lightmap must be
7791 // applied to the color
7792 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7793 if (model->type == mod_brushq3)
7794 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7795 colorscale *= r_refdef.lightmapintensity;
7796 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7797 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7798 // basic lit geometry
7799 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]);
7800 // add pants/shirt if needed
7801 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7802 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]);
7803 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7804 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]);
7805 // now add ambient passes if needed
7806 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7808 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]);
7809 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7810 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]);
7811 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7812 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]);
7815 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7816 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]);
7817 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7819 // if this is opaque use alpha blend which will darken the earlier
7822 // if this is an alpha blended material, all the earlier passes
7823 // were darkened by fog already, so we only need to add the fog
7824 // color ontop through the fog mask texture
7826 // if this is an additive blended material, all the earlier passes
7827 // were darkened by fog already, and we should not add fog color
7828 // (because the background was not darkened, there is no fog color
7829 // that was lost behind it).
7830 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]);
7834 return t->currentframe;
7837 rsurfacestate_t rsurface;
7839 void RSurf_ActiveWorldEntity(void)
7841 dp_model_t *model = r_refdef.scene.worldmodel;
7842 //if (rsurface.entity == r_refdef.scene.worldentity)
7844 rsurface.entity = r_refdef.scene.worldentity;
7845 rsurface.skeleton = NULL;
7846 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7847 rsurface.ent_skinnum = 0;
7848 rsurface.ent_qwskin = -1;
7849 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7850 rsurface.shadertime = r_refdef.scene.time;
7851 rsurface.matrix = identitymatrix;
7852 rsurface.inversematrix = identitymatrix;
7853 rsurface.matrixscale = 1;
7854 rsurface.inversematrixscale = 1;
7855 R_EntityMatrix(&identitymatrix);
7856 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7857 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7858 rsurface.fograngerecip = r_refdef.fograngerecip;
7859 rsurface.fogheightfade = r_refdef.fogheightfade;
7860 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7861 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7862 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7863 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7864 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7865 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7866 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7867 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7868 rsurface.colormod[3] = 1;
7869 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);
7870 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7871 rsurface.frameblend[0].lerp = 1;
7872 rsurface.ent_alttextures = false;
7873 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7874 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7875 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7876 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7877 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7878 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7879 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7880 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7881 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7882 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7883 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7884 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7885 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7886 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7887 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7888 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7889 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7890 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7891 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7892 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7893 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7894 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7895 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7896 rsurface.modelelement3i = model->surfmesh.data_element3i;
7897 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7898 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7899 rsurface.modelelement3s = model->surfmesh.data_element3s;
7900 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7901 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7902 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7903 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7904 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7905 rsurface.modelsurfaces = model->data_surfaces;
7906 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7907 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7908 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7909 rsurface.modelgeneratedvertex = false;
7910 rsurface.batchgeneratedvertex = false;
7911 rsurface.batchfirstvertex = 0;
7912 rsurface.batchnumvertices = 0;
7913 rsurface.batchfirsttriangle = 0;
7914 rsurface.batchnumtriangles = 0;
7915 rsurface.batchvertex3f = NULL;
7916 rsurface.batchvertex3f_vertexbuffer = NULL;
7917 rsurface.batchvertex3f_bufferoffset = 0;
7918 rsurface.batchsvector3f = NULL;
7919 rsurface.batchsvector3f_vertexbuffer = NULL;
7920 rsurface.batchsvector3f_bufferoffset = 0;
7921 rsurface.batchtvector3f = NULL;
7922 rsurface.batchtvector3f_vertexbuffer = NULL;
7923 rsurface.batchtvector3f_bufferoffset = 0;
7924 rsurface.batchnormal3f = NULL;
7925 rsurface.batchnormal3f_vertexbuffer = NULL;
7926 rsurface.batchnormal3f_bufferoffset = 0;
7927 rsurface.batchlightmapcolor4f = NULL;
7928 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7929 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7930 rsurface.batchtexcoordtexture2f = NULL;
7931 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7932 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7933 rsurface.batchtexcoordlightmap2f = NULL;
7934 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7935 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7936 rsurface.batchvertexmesh = NULL;
7937 rsurface.batchvertexmeshbuffer = NULL;
7938 rsurface.batchvertex3fbuffer = NULL;
7939 rsurface.batchelement3i = NULL;
7940 rsurface.batchelement3i_indexbuffer = NULL;
7941 rsurface.batchelement3i_bufferoffset = 0;
7942 rsurface.batchelement3s = NULL;
7943 rsurface.batchelement3s_indexbuffer = NULL;
7944 rsurface.batchelement3s_bufferoffset = 0;
7945 rsurface.passcolor4f = NULL;
7946 rsurface.passcolor4f_vertexbuffer = NULL;
7947 rsurface.passcolor4f_bufferoffset = 0;
7950 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7952 dp_model_t *model = ent->model;
7953 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7955 rsurface.entity = (entity_render_t *)ent;
7956 rsurface.skeleton = ent->skeleton;
7957 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7958 rsurface.ent_skinnum = ent->skinnum;
7959 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;
7960 rsurface.ent_flags = ent->flags;
7961 rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
7962 rsurface.matrix = ent->matrix;
7963 rsurface.inversematrix = ent->inversematrix;
7964 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7965 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7966 R_EntityMatrix(&rsurface.matrix);
7967 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7968 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7969 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7970 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7971 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7972 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7973 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7974 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7975 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7976 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7977 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7978 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7979 rsurface.colormod[3] = ent->alpha;
7980 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7981 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7982 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7983 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7984 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7985 if (ent->model->brush.submodel && !prepass)
7987 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7988 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7990 if (model->surfmesh.isanimated && model->AnimateVertices)
7992 if (ent->animcache_vertex3f)
7994 rsurface.modelvertex3f = ent->animcache_vertex3f;
7995 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7996 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7997 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7998 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7999 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8000 rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8002 else if (wanttangents)
8004 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8005 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8006 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8007 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8008 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8009 rsurface.modelvertexmesh = NULL;
8010 rsurface.modelvertexmeshbuffer = NULL;
8011 rsurface.modelvertex3fbuffer = NULL;
8013 else if (wantnormals)
8015 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8016 rsurface.modelsvector3f = NULL;
8017 rsurface.modeltvector3f = NULL;
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, NULL, NULL);
8020 rsurface.modelvertexmesh = NULL;
8021 rsurface.modelvertexmeshbuffer = NULL;
8022 rsurface.modelvertex3fbuffer = NULL;
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 = NULL;
8030 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8031 rsurface.modelvertexmesh = NULL;
8032 rsurface.modelvertexmeshbuffer = NULL;
8033 rsurface.modelvertex3fbuffer = NULL;
8035 rsurface.modelvertex3f_vertexbuffer = 0;
8036 rsurface.modelvertex3f_bufferoffset = 0;
8037 rsurface.modelsvector3f_vertexbuffer = 0;
8038 rsurface.modelsvector3f_bufferoffset = 0;
8039 rsurface.modeltvector3f_vertexbuffer = 0;
8040 rsurface.modeltvector3f_bufferoffset = 0;
8041 rsurface.modelnormal3f_vertexbuffer = 0;
8042 rsurface.modelnormal3f_bufferoffset = 0;
8043 rsurface.modelgeneratedvertex = true;
8047 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8048 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8049 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8050 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8051 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8052 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8053 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8054 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8055 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8056 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8057 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8058 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8059 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8060 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8061 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8062 rsurface.modelgeneratedvertex = false;
8064 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8065 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8066 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8067 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8068 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8069 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8070 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8071 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8072 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8073 rsurface.modelelement3i = model->surfmesh.data_element3i;
8074 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8075 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8076 rsurface.modelelement3s = model->surfmesh.data_element3s;
8077 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8078 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8079 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8080 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8081 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8082 rsurface.modelsurfaces = model->data_surfaces;
8083 rsurface.batchgeneratedvertex = false;
8084 rsurface.batchfirstvertex = 0;
8085 rsurface.batchnumvertices = 0;
8086 rsurface.batchfirsttriangle = 0;
8087 rsurface.batchnumtriangles = 0;
8088 rsurface.batchvertex3f = NULL;
8089 rsurface.batchvertex3f_vertexbuffer = NULL;
8090 rsurface.batchvertex3f_bufferoffset = 0;
8091 rsurface.batchsvector3f = NULL;
8092 rsurface.batchsvector3f_vertexbuffer = NULL;
8093 rsurface.batchsvector3f_bufferoffset = 0;
8094 rsurface.batchtvector3f = NULL;
8095 rsurface.batchtvector3f_vertexbuffer = NULL;
8096 rsurface.batchtvector3f_bufferoffset = 0;
8097 rsurface.batchnormal3f = NULL;
8098 rsurface.batchnormal3f_vertexbuffer = NULL;
8099 rsurface.batchnormal3f_bufferoffset = 0;
8100 rsurface.batchlightmapcolor4f = NULL;
8101 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8102 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8103 rsurface.batchtexcoordtexture2f = NULL;
8104 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8105 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8106 rsurface.batchtexcoordlightmap2f = NULL;
8107 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8108 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8109 rsurface.batchvertexmesh = NULL;
8110 rsurface.batchvertexmeshbuffer = NULL;
8111 rsurface.batchvertex3fbuffer = NULL;
8112 rsurface.batchelement3i = NULL;
8113 rsurface.batchelement3i_indexbuffer = NULL;
8114 rsurface.batchelement3i_bufferoffset = 0;
8115 rsurface.batchelement3s = NULL;
8116 rsurface.batchelement3s_indexbuffer = NULL;
8117 rsurface.batchelement3s_bufferoffset = 0;
8118 rsurface.passcolor4f = NULL;
8119 rsurface.passcolor4f_vertexbuffer = NULL;
8120 rsurface.passcolor4f_bufferoffset = 0;
8123 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)
8125 rsurface.entity = r_refdef.scene.worldentity;
8126 rsurface.skeleton = NULL;
8127 rsurface.ent_skinnum = 0;
8128 rsurface.ent_qwskin = -1;
8129 rsurface.ent_flags = entflags;
8130 rsurface.shadertime = r_refdef.scene.time - shadertime;
8131 rsurface.modelnumvertices = numvertices;
8132 rsurface.modelnumtriangles = numtriangles;
8133 rsurface.matrix = *matrix;
8134 rsurface.inversematrix = *inversematrix;
8135 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8136 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8137 R_EntityMatrix(&rsurface.matrix);
8138 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8139 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8140 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8141 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8142 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8143 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8144 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8145 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8146 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8147 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8148 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8149 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8150 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);
8151 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8152 rsurface.frameblend[0].lerp = 1;
8153 rsurface.ent_alttextures = false;
8154 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8155 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8158 rsurface.modelvertex3f = (float *)vertex3f;
8159 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8160 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8161 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8163 else if (wantnormals)
8165 rsurface.modelvertex3f = (float *)vertex3f;
8166 rsurface.modelsvector3f = NULL;
8167 rsurface.modeltvector3f = NULL;
8168 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8172 rsurface.modelvertex3f = (float *)vertex3f;
8173 rsurface.modelsvector3f = NULL;
8174 rsurface.modeltvector3f = NULL;
8175 rsurface.modelnormal3f = NULL;
8177 rsurface.modelvertexmesh = NULL;
8178 rsurface.modelvertexmeshbuffer = NULL;
8179 rsurface.modelvertex3fbuffer = NULL;
8180 rsurface.modelvertex3f_vertexbuffer = 0;
8181 rsurface.modelvertex3f_bufferoffset = 0;
8182 rsurface.modelsvector3f_vertexbuffer = 0;
8183 rsurface.modelsvector3f_bufferoffset = 0;
8184 rsurface.modeltvector3f_vertexbuffer = 0;
8185 rsurface.modeltvector3f_bufferoffset = 0;
8186 rsurface.modelnormal3f_vertexbuffer = 0;
8187 rsurface.modelnormal3f_bufferoffset = 0;
8188 rsurface.modelgeneratedvertex = true;
8189 rsurface.modellightmapcolor4f = (float *)color4f;
8190 rsurface.modellightmapcolor4f_vertexbuffer = 0;
8191 rsurface.modellightmapcolor4f_bufferoffset = 0;
8192 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
8193 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8194 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8195 rsurface.modeltexcoordlightmap2f = NULL;
8196 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8197 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8198 rsurface.modelelement3i = (int *)element3i;
8199 rsurface.modelelement3i_indexbuffer = NULL;
8200 rsurface.modelelement3i_bufferoffset = 0;
8201 rsurface.modelelement3s = (unsigned short *)element3s;
8202 rsurface.modelelement3s_indexbuffer = NULL;
8203 rsurface.modelelement3s_bufferoffset = 0;
8204 rsurface.modellightmapoffsets = NULL;
8205 rsurface.modelsurfaces = NULL;
8206 rsurface.batchgeneratedvertex = false;
8207 rsurface.batchfirstvertex = 0;
8208 rsurface.batchnumvertices = 0;
8209 rsurface.batchfirsttriangle = 0;
8210 rsurface.batchnumtriangles = 0;
8211 rsurface.batchvertex3f = NULL;
8212 rsurface.batchvertex3f_vertexbuffer = NULL;
8213 rsurface.batchvertex3f_bufferoffset = 0;
8214 rsurface.batchsvector3f = NULL;
8215 rsurface.batchsvector3f_vertexbuffer = NULL;
8216 rsurface.batchsvector3f_bufferoffset = 0;
8217 rsurface.batchtvector3f = NULL;
8218 rsurface.batchtvector3f_vertexbuffer = NULL;
8219 rsurface.batchtvector3f_bufferoffset = 0;
8220 rsurface.batchnormal3f = NULL;
8221 rsurface.batchnormal3f_vertexbuffer = NULL;
8222 rsurface.batchnormal3f_bufferoffset = 0;
8223 rsurface.batchlightmapcolor4f = NULL;
8224 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8225 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8226 rsurface.batchtexcoordtexture2f = NULL;
8227 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8228 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8229 rsurface.batchtexcoordlightmap2f = NULL;
8230 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8231 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8232 rsurface.batchvertexmesh = NULL;
8233 rsurface.batchvertexmeshbuffer = NULL;
8234 rsurface.batchvertex3fbuffer = NULL;
8235 rsurface.batchelement3i = NULL;
8236 rsurface.batchelement3i_indexbuffer = NULL;
8237 rsurface.batchelement3i_bufferoffset = 0;
8238 rsurface.batchelement3s = NULL;
8239 rsurface.batchelement3s_indexbuffer = NULL;
8240 rsurface.batchelement3s_bufferoffset = 0;
8241 rsurface.passcolor4f = NULL;
8242 rsurface.passcolor4f_vertexbuffer = NULL;
8243 rsurface.passcolor4f_bufferoffset = 0;
8245 if (rsurface.modelnumvertices && rsurface.modelelement3i)
8247 if ((wantnormals || wanttangents) && !normal3f)
8249 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8250 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8252 if (wanttangents && !svector3f)
8254 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8255 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8256 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8261 float RSurf_FogPoint(const float *v)
8263 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8264 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8265 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8266 float FogHeightFade = r_refdef.fogheightfade;
8268 unsigned int fogmasktableindex;
8269 if (r_refdef.fogplaneviewabove)
8270 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8272 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8273 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8274 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8277 float RSurf_FogVertex(const float *v)
8279 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8280 float FogPlaneViewDist = rsurface.fogplaneviewdist;
8281 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8282 float FogHeightFade = rsurface.fogheightfade;
8284 unsigned int fogmasktableindex;
8285 if (r_refdef.fogplaneviewabove)
8286 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8288 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8289 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8290 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8293 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8296 for (i = 0;i < numelements;i++)
8297 outelement3i[i] = inelement3i[i] + adjust;
8300 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8301 extern cvar_t gl_vbo;
8302 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8310 int surfacefirsttriangle;
8311 int surfacenumtriangles;
8312 int surfacefirstvertex;
8313 int surfaceendvertex;
8314 int surfacenumvertices;
8315 int batchnumvertices;
8316 int batchnumtriangles;
8320 qboolean dynamicvertex;
8324 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8326 q3shaderinfo_deform_t *deform;
8327 const msurface_t *surface, *firstsurface;
8328 r_vertexmesh_t *vertexmesh;
8329 if (!texturenumsurfaces)
8331 // find vertex range of this surface batch
8333 firstsurface = texturesurfacelist[0];
8334 firsttriangle = firstsurface->num_firsttriangle;
8335 batchnumvertices = 0;
8336 batchnumtriangles = 0;
8337 firstvertex = endvertex = firstsurface->num_firstvertex;
8338 for (i = 0;i < texturenumsurfaces;i++)
8340 surface = texturesurfacelist[i];
8341 if (surface != firstsurface + i)
8343 surfacefirstvertex = surface->num_firstvertex;
8344 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8345 surfacenumvertices = surface->num_vertices;
8346 surfacenumtriangles = surface->num_triangles;
8347 if (firstvertex > surfacefirstvertex)
8348 firstvertex = surfacefirstvertex;
8349 if (endvertex < surfaceendvertex)
8350 endvertex = surfaceendvertex;
8351 batchnumvertices += surfacenumvertices;
8352 batchnumtriangles += surfacenumtriangles;
8355 // we now know the vertex range used, and if there are any gaps in it
8356 rsurface.batchfirstvertex = firstvertex;
8357 rsurface.batchnumvertices = endvertex - firstvertex;
8358 rsurface.batchfirsttriangle = firsttriangle;
8359 rsurface.batchnumtriangles = batchnumtriangles;
8361 // this variable holds flags for which properties have been updated that
8362 // may require regenerating vertexmesh array...
8365 // check if any dynamic vertex processing must occur
8366 dynamicvertex = false;
8368 // if there is a chance of animated vertex colors, it's a dynamic batch
8369 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8371 dynamicvertex = true;
8372 batchneed |= BATCHNEED_NOGAPS;
8373 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8376 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8378 switch (deform->deform)
8381 case Q3DEFORM_PROJECTIONSHADOW:
8382 case Q3DEFORM_TEXT0:
8383 case Q3DEFORM_TEXT1:
8384 case Q3DEFORM_TEXT2:
8385 case Q3DEFORM_TEXT3:
8386 case Q3DEFORM_TEXT4:
8387 case Q3DEFORM_TEXT5:
8388 case Q3DEFORM_TEXT6:
8389 case Q3DEFORM_TEXT7:
8392 case Q3DEFORM_AUTOSPRITE:
8393 dynamicvertex = true;
8394 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8395 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8397 case Q3DEFORM_AUTOSPRITE2:
8398 dynamicvertex = true;
8399 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8400 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8402 case Q3DEFORM_NORMAL:
8403 dynamicvertex = true;
8404 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8405 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8408 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8409 break; // if wavefunc is a nop, ignore this transform
8410 dynamicvertex = true;
8411 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8412 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8414 case Q3DEFORM_BULGE:
8415 dynamicvertex = true;
8416 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8417 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8420 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8421 break; // if wavefunc is a nop, ignore this transform
8422 dynamicvertex = true;
8423 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8424 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8428 switch(rsurface.texture->tcgen.tcgen)
8431 case Q3TCGEN_TEXTURE:
8433 case Q3TCGEN_LIGHTMAP:
8434 dynamicvertex = true;
8435 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8436 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8438 case Q3TCGEN_VECTOR:
8439 dynamicvertex = true;
8440 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8441 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8443 case Q3TCGEN_ENVIRONMENT:
8444 dynamicvertex = true;
8445 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8446 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8449 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8451 dynamicvertex = true;
8452 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8453 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8456 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8458 dynamicvertex = true;
8459 batchneed |= BATCHNEED_NOGAPS;
8460 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8463 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8465 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8466 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
8467 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
8468 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
8469 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8470 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8471 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8474 // when the model data has no vertex buffer (dynamic mesh), we need to
8476 if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8477 batchneed |= BATCHNEED_NOGAPS;
8479 // if needsupdate, we have to do a dynamic vertex batch for sure
8480 if (needsupdate & batchneed)
8481 dynamicvertex = true;
8483 // see if we need to build vertexmesh from arrays
8484 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8485 dynamicvertex = true;
8487 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8488 // also some drivers strongly dislike firstvertex
8489 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8490 dynamicvertex = true;
8492 rsurface.batchvertex3f = rsurface.modelvertex3f;
8493 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8494 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8495 rsurface.batchsvector3f = rsurface.modelsvector3f;
8496 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8497 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8498 rsurface.batchtvector3f = rsurface.modeltvector3f;
8499 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8500 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8501 rsurface.batchnormal3f = rsurface.modelnormal3f;
8502 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8503 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8504 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8505 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
8506 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8507 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8508 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
8509 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
8510 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8511 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8512 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8513 rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8514 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8515 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8516 rsurface.batchelement3i = rsurface.modelelement3i;
8517 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8518 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8519 rsurface.batchelement3s = rsurface.modelelement3s;
8520 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8521 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8523 // if any dynamic vertex processing has to occur in software, we copy the
8524 // entire surface list together before processing to rebase the vertices
8525 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8527 // if any gaps exist and we do not have a static vertex buffer, we have to
8528 // copy the surface list together to avoid wasting upload bandwidth on the
8529 // vertices in the gaps.
8531 // if gaps exist and we have a static vertex buffer, we still have to
8532 // combine the index buffer ranges into one dynamic index buffer.
8534 // in all cases we end up with data that can be drawn in one call.
8538 // static vertex data, just set pointers...
8539 rsurface.batchgeneratedvertex = false;
8540 // if there are gaps, we want to build a combined index buffer,
8541 // otherwise use the original static buffer with an appropriate offset
8544 // build a new triangle elements array for this batch
8545 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8546 rsurface.batchfirsttriangle = 0;
8548 for (i = 0;i < texturenumsurfaces;i++)
8550 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8551 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8552 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8553 numtriangles += surfacenumtriangles;
8555 rsurface.batchelement3i_indexbuffer = NULL;
8556 rsurface.batchelement3i_bufferoffset = 0;
8557 rsurface.batchelement3s = NULL;
8558 rsurface.batchelement3s_indexbuffer = NULL;
8559 rsurface.batchelement3s_bufferoffset = 0;
8560 if (endvertex <= 65536)
8562 // make a 16bit (unsigned short) index array if possible
8563 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8564 for (i = 0;i < numtriangles*3;i++)
8565 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8571 // something needs software processing, do it for real...
8572 // we only directly handle separate array data in this case and then
8573 // generate interleaved data if needed...
8574 rsurface.batchgeneratedvertex = true;
8576 // now copy the vertex data into a combined array and make an index array
8577 // (this is what Quake3 does all the time)
8578 //if (gaps || rsurface.batchfirstvertex)
8580 rsurface.batchvertex3fbuffer = NULL;
8581 rsurface.batchvertexmesh = NULL;
8582 rsurface.batchvertexmeshbuffer = NULL;
8583 rsurface.batchvertex3f = NULL;
8584 rsurface.batchvertex3f_vertexbuffer = NULL;
8585 rsurface.batchvertex3f_bufferoffset = 0;
8586 rsurface.batchsvector3f = NULL;
8587 rsurface.batchsvector3f_vertexbuffer = NULL;
8588 rsurface.batchsvector3f_bufferoffset = 0;
8589 rsurface.batchtvector3f = NULL;
8590 rsurface.batchtvector3f_vertexbuffer = NULL;
8591 rsurface.batchtvector3f_bufferoffset = 0;
8592 rsurface.batchnormal3f = NULL;
8593 rsurface.batchnormal3f_vertexbuffer = NULL;
8594 rsurface.batchnormal3f_bufferoffset = 0;
8595 rsurface.batchlightmapcolor4f = NULL;
8596 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8597 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8598 rsurface.batchtexcoordtexture2f = NULL;
8599 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8600 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8601 rsurface.batchtexcoordlightmap2f = NULL;
8602 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8603 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8604 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8605 rsurface.batchelement3i_indexbuffer = NULL;
8606 rsurface.batchelement3i_bufferoffset = 0;
8607 rsurface.batchelement3s = NULL;
8608 rsurface.batchelement3s_indexbuffer = NULL;
8609 rsurface.batchelement3s_bufferoffset = 0;
8610 // we'll only be setting up certain arrays as needed
8611 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8612 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8613 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8614 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8615 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8616 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8617 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8619 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8620 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8622 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8623 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8624 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8625 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8626 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8627 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8630 for (i = 0;i < texturenumsurfaces;i++)
8632 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8633 surfacenumvertices = texturesurfacelist[i]->num_vertices;
8634 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8635 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8636 // copy only the data requested
8637 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8638 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8639 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8641 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8643 if (rsurface.batchvertex3f)
8644 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8646 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8648 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8650 if (rsurface.modelnormal3f)
8651 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8653 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8655 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8657 if (rsurface.modelsvector3f)
8659 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8660 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8664 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8665 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8668 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8670 if (rsurface.modellightmapcolor4f)
8671 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8673 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
8675 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8677 if (rsurface.modeltexcoordtexture2f)
8678 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8680 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8682 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8684 if (rsurface.modeltexcoordlightmap2f)
8685 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8687 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8690 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8691 numvertices += surfacenumvertices;
8692 numtriangles += surfacenumtriangles;
8695 // generate a 16bit index array as well if possible
8696 // (in general, dynamic batches fit)
8697 if (numvertices <= 65536)
8699 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8700 for (i = 0;i < numtriangles*3;i++)
8701 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8704 // since we've copied everything, the batch now starts at 0
8705 rsurface.batchfirstvertex = 0;
8706 rsurface.batchnumvertices = batchnumvertices;
8707 rsurface.batchfirsttriangle = 0;
8708 rsurface.batchnumtriangles = batchnumtriangles;
8711 // q1bsp surfaces rendered in vertex color mode have to have colors
8712 // calculated based on lightstyles
8713 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8715 // generate color arrays for the surfaces in this list
8720 const unsigned char *lm;
8721 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8722 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8723 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8725 for (i = 0;i < texturenumsurfaces;i++)
8727 surface = texturesurfacelist[i];
8728 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8729 surfacenumvertices = surface->num_vertices;
8730 if (surface->lightmapinfo->samples)
8732 for (j = 0;j < surfacenumvertices;j++)
8734 lm = surface->lightmapinfo->samples + offsets[j];
8735 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8736 VectorScale(lm, scale, c);
8737 if (surface->lightmapinfo->styles[1] != 255)
8739 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8741 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8742 VectorMA(c, scale, lm, c);
8743 if (surface->lightmapinfo->styles[2] != 255)
8746 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8747 VectorMA(c, scale, lm, c);
8748 if (surface->lightmapinfo->styles[3] != 255)
8751 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8752 VectorMA(c, scale, lm, c);
8759 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);
8765 for (j = 0;j < surfacenumvertices;j++)
8767 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8774 // if vertices are deformed (sprite flares and things in maps, possibly
8775 // water waves, bulges and other deformations), modify the copied vertices
8777 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8779 switch (deform->deform)
8782 case Q3DEFORM_PROJECTIONSHADOW:
8783 case Q3DEFORM_TEXT0:
8784 case Q3DEFORM_TEXT1:
8785 case Q3DEFORM_TEXT2:
8786 case Q3DEFORM_TEXT3:
8787 case Q3DEFORM_TEXT4:
8788 case Q3DEFORM_TEXT5:
8789 case Q3DEFORM_TEXT6:
8790 case Q3DEFORM_TEXT7:
8793 case Q3DEFORM_AUTOSPRITE:
8794 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8795 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8796 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8797 VectorNormalize(newforward);
8798 VectorNormalize(newright);
8799 VectorNormalize(newup);
8800 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8801 // rsurface.batchvertex3f_vertexbuffer = NULL;
8802 // rsurface.batchvertex3f_bufferoffset = 0;
8803 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8804 // rsurface.batchsvector3f_vertexbuffer = NULL;
8805 // rsurface.batchsvector3f_bufferoffset = 0;
8806 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8807 // rsurface.batchtvector3f_vertexbuffer = NULL;
8808 // rsurface.batchtvector3f_bufferoffset = 0;
8809 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8810 // rsurface.batchnormal3f_vertexbuffer = NULL;
8811 // rsurface.batchnormal3f_bufferoffset = 0;
8812 // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
8813 if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
8814 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8815 if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
8816 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);
8817 // a single autosprite surface can contain multiple sprites...
8818 for (j = 0;j < batchnumvertices - 3;j += 4)
8820 VectorClear(center);
8821 for (i = 0;i < 4;i++)
8822 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8823 VectorScale(center, 0.25f, center);
8824 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8825 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8826 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8827 for (i = 0;i < 4;i++)
8829 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8830 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8833 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8834 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8835 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);
8837 case Q3DEFORM_AUTOSPRITE2:
8838 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8839 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8840 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8841 VectorNormalize(newforward);
8842 VectorNormalize(newright);
8843 VectorNormalize(newup);
8844 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8845 // rsurface.batchvertex3f_vertexbuffer = NULL;
8846 // rsurface.batchvertex3f_bufferoffset = 0;
8848 const float *v1, *v2;
8858 memset(shortest, 0, sizeof(shortest));
8859 // a single autosprite surface can contain multiple sprites...
8860 for (j = 0;j < batchnumvertices - 3;j += 4)
8862 VectorClear(center);
8863 for (i = 0;i < 4;i++)
8864 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8865 VectorScale(center, 0.25f, center);
8866 // find the two shortest edges, then use them to define the
8867 // axis vectors for rotating around the central axis
8868 for (i = 0;i < 6;i++)
8870 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8871 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8872 l = VectorDistance2(v1, v2);
8873 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8875 l += (1.0f / 1024.0f);
8876 if (shortest[0].length2 > l || i == 0)
8878 shortest[1] = shortest[0];
8879 shortest[0].length2 = l;
8880 shortest[0].v1 = v1;
8881 shortest[0].v2 = v2;
8883 else if (shortest[1].length2 > l || i == 1)
8885 shortest[1].length2 = l;
8886 shortest[1].v1 = v1;
8887 shortest[1].v2 = v2;
8890 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8891 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8892 // this calculates the right vector from the shortest edge
8893 // and the up vector from the edge midpoints
8894 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8895 VectorNormalize(right);
8896 VectorSubtract(end, start, up);
8897 VectorNormalize(up);
8898 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8899 VectorSubtract(rsurface.localvieworigin, center, forward);
8900 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8901 VectorNegate(forward, forward);
8902 VectorReflect(forward, 0, up, forward);
8903 VectorNormalize(forward);
8904 CrossProduct(up, forward, newright);
8905 VectorNormalize(newright);
8906 // rotate the quad around the up axis vector, this is made
8907 // especially easy by the fact we know the quad is flat,
8908 // so we only have to subtract the center position and
8909 // measure distance along the right vector, and then
8910 // multiply that by the newright vector and add back the
8912 // we also need to subtract the old position to undo the
8913 // displacement from the center, which we do with a
8914 // DotProduct, the subtraction/addition of center is also
8915 // optimized into DotProducts here
8916 l = DotProduct(right, center);
8917 for (i = 0;i < 4;i++)
8919 v1 = rsurface.batchvertex3f + 3*(j+i);
8920 f = DotProduct(right, v1) - l;
8921 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8925 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8927 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8928 // rsurface.batchnormal3f_vertexbuffer = NULL;
8929 // rsurface.batchnormal3f_bufferoffset = 0;
8930 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8932 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8934 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8935 // rsurface.batchsvector3f_vertexbuffer = NULL;
8936 // rsurface.batchsvector3f_bufferoffset = 0;
8937 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8938 // rsurface.batchtvector3f_vertexbuffer = NULL;
8939 // rsurface.batchtvector3f_bufferoffset = 0;
8940 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);
8943 case Q3DEFORM_NORMAL:
8944 // deform the normals to make reflections wavey
8945 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8946 rsurface.batchnormal3f_vertexbuffer = NULL;
8947 rsurface.batchnormal3f_bufferoffset = 0;
8948 for (j = 0;j < batchnumvertices;j++)
8951 float *normal = rsurface.batchnormal3f + 3*j;
8952 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8953 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
8954 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
8955 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
8956 VectorNormalize(normal);
8958 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8960 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8961 // rsurface.batchsvector3f_vertexbuffer = NULL;
8962 // rsurface.batchsvector3f_bufferoffset = 0;
8963 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8964 // rsurface.batchtvector3f_vertexbuffer = NULL;
8965 // rsurface.batchtvector3f_bufferoffset = 0;
8966 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);
8970 // deform vertex array to make wavey water and flags and such
8971 waveparms[0] = deform->waveparms[0];
8972 waveparms[1] = deform->waveparms[1];
8973 waveparms[2] = deform->waveparms[2];
8974 waveparms[3] = deform->waveparms[3];
8975 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8976 break; // if wavefunc is a nop, don't make a dynamic vertex array
8977 // this is how a divisor of vertex influence on deformation
8978 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8979 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8980 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8981 // rsurface.batchvertex3f_vertexbuffer = NULL;
8982 // rsurface.batchvertex3f_bufferoffset = 0;
8983 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8984 // rsurface.batchnormal3f_vertexbuffer = NULL;
8985 // rsurface.batchnormal3f_bufferoffset = 0;
8986 for (j = 0;j < batchnumvertices;j++)
8988 // if the wavefunc depends on time, evaluate it per-vertex
8991 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8992 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8994 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8996 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8997 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8998 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9000 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9001 // rsurface.batchsvector3f_vertexbuffer = NULL;
9002 // rsurface.batchsvector3f_bufferoffset = 0;
9003 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9004 // rsurface.batchtvector3f_vertexbuffer = NULL;
9005 // rsurface.batchtvector3f_bufferoffset = 0;
9006 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);
9009 case Q3DEFORM_BULGE:
9010 // deform vertex array to make the surface have moving bulges
9011 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9012 // rsurface.batchvertex3f_vertexbuffer = NULL;
9013 // rsurface.batchvertex3f_bufferoffset = 0;
9014 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9015 // rsurface.batchnormal3f_vertexbuffer = NULL;
9016 // rsurface.batchnormal3f_bufferoffset = 0;
9017 for (j = 0;j < batchnumvertices;j++)
9019 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9020 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9022 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9023 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9024 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9026 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9027 // rsurface.batchsvector3f_vertexbuffer = NULL;
9028 // rsurface.batchsvector3f_bufferoffset = 0;
9029 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9030 // rsurface.batchtvector3f_vertexbuffer = NULL;
9031 // rsurface.batchtvector3f_bufferoffset = 0;
9032 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);
9036 // deform vertex array
9037 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9038 break; // if wavefunc is a nop, don't make a dynamic vertex array
9039 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9040 VectorScale(deform->parms, scale, waveparms);
9041 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9042 // rsurface.batchvertex3f_vertexbuffer = NULL;
9043 // rsurface.batchvertex3f_bufferoffset = 0;
9044 for (j = 0;j < batchnumvertices;j++)
9045 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9050 // generate texcoords based on the chosen texcoord source
9051 switch(rsurface.texture->tcgen.tcgen)
9054 case Q3TCGEN_TEXTURE:
9056 case Q3TCGEN_LIGHTMAP:
9057 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9058 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9059 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9060 if (rsurface.batchtexcoordlightmap2f)
9061 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9063 case Q3TCGEN_VECTOR:
9064 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9065 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9066 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9067 for (j = 0;j < batchnumvertices;j++)
9069 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9070 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9073 case Q3TCGEN_ENVIRONMENT:
9074 // make environment reflections using a spheremap
9075 rsurface.batchtexcoordtexture2f = (float *)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 // identical to Q3A's method, but executed in worldspace so
9081 // carried models can be shiny too
9083 float viewer[3], d, reflected[3], worldreflected[3];
9085 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9086 // VectorNormalize(viewer);
9088 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9090 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9091 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9092 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9093 // note: this is proportinal to viewer, so we can normalize later
9095 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9096 VectorNormalize(worldreflected);
9098 // note: this sphere map only uses world x and z!
9099 // so positive and negative y will LOOK THE SAME.
9100 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9101 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9105 // the only tcmod that needs software vertex processing is turbulent, so
9106 // check for it here and apply the changes if needed
9107 // and we only support that as the first one
9108 // (handling a mixture of turbulent and other tcmods would be problematic
9109 // without punting it entirely to a software path)
9110 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9112 amplitude = rsurface.texture->tcmods[0].parms[1];
9113 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9114 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9115 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9116 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9117 for (j = 0;j < batchnumvertices;j++)
9119 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);
9120 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9124 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9126 // convert the modified arrays to vertex structs
9127 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9128 // rsurface.batchvertexmeshbuffer = NULL;
9129 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9130 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9131 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9132 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9133 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9134 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9135 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9137 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9139 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9140 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9143 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9144 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9145 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9146 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9147 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9148 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9149 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9150 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9151 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9155 void RSurf_DrawBatch(void)
9157 // sometimes a zero triangle surface (usually a degenerate patch) makes it
9158 // through the pipeline, killing it earlier in the pipeline would have
9159 // per-surface overhead rather than per-batch overhead, so it's best to
9160 // reject it here, before it hits glDraw.
9161 if (rsurface.batchnumtriangles == 0)
9164 // batch debugging code
9165 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9171 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9172 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9175 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9177 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9179 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9180 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);
9187 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);
9190 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9192 // pick the closest matching water plane
9193 int planeindex, vertexindex, bestplaneindex = -1;
9197 r_waterstate_waterplane_t *p;
9198 qboolean prepared = false;
9200 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9202 if(p->camera_entity != rsurface.texture->camera_entity)
9207 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9209 if(rsurface.batchnumvertices == 0)
9212 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9214 Matrix4x4_Transform(&rsurface.matrix, v, vert);
9215 d += fabs(PlaneDiff(vert, &p->plane));
9217 if (bestd > d || bestplaneindex < 0)
9220 bestplaneindex = planeindex;
9223 return bestplaneindex;
9224 // NOTE: this MAY return a totally unrelated water plane; we can ignore
9225 // this situation though, as it might be better to render single larger
9226 // batches with useless stuff (backface culled for example) than to
9227 // render multiple smaller batches
9230 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9233 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9234 rsurface.passcolor4f_vertexbuffer = 0;
9235 rsurface.passcolor4f_bufferoffset = 0;
9236 for (i = 0;i < rsurface.batchnumvertices;i++)
9237 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9240 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9247 if (rsurface.passcolor4f)
9249 // generate color arrays
9250 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9251 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9252 rsurface.passcolor4f_vertexbuffer = 0;
9253 rsurface.passcolor4f_bufferoffset = 0;
9254 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)
9256 f = RSurf_FogVertex(v);
9265 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9266 rsurface.passcolor4f_vertexbuffer = 0;
9267 rsurface.passcolor4f_bufferoffset = 0;
9268 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9270 f = RSurf_FogVertex(v);
9279 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9286 if (!rsurface.passcolor4f)
9288 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9289 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9290 rsurface.passcolor4f_vertexbuffer = 0;
9291 rsurface.passcolor4f_bufferoffset = 0;
9292 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)
9294 f = RSurf_FogVertex(v);
9295 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9296 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9297 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9302 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9307 if (!rsurface.passcolor4f)
9309 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9310 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9311 rsurface.passcolor4f_vertexbuffer = 0;
9312 rsurface.passcolor4f_bufferoffset = 0;
9313 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9322 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9327 if (!rsurface.passcolor4f)
9329 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9330 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9331 rsurface.passcolor4f_vertexbuffer = 0;
9332 rsurface.passcolor4f_bufferoffset = 0;
9333 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9335 c2[0] = c[0] + r_refdef.scene.ambient;
9336 c2[1] = c[1] + r_refdef.scene.ambient;
9337 c2[2] = c[2] + r_refdef.scene.ambient;
9342 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9345 rsurface.passcolor4f = NULL;
9346 rsurface.passcolor4f_vertexbuffer = 0;
9347 rsurface.passcolor4f_bufferoffset = 0;
9348 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9349 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9350 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9351 GL_Color(r, g, b, a);
9352 R_Mesh_TexBind(0, rsurface.lightmaptexture);
9356 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9358 // TODO: optimize applyfog && applycolor case
9359 // just apply fog if necessary, and tint the fog color array if necessary
9360 rsurface.passcolor4f = NULL;
9361 rsurface.passcolor4f_vertexbuffer = 0;
9362 rsurface.passcolor4f_bufferoffset = 0;
9363 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9364 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9365 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9366 GL_Color(r, g, b, a);
9370 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9373 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9374 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9375 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9376 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9377 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9378 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9379 GL_Color(r, g, b, a);
9383 static void RSurf_DrawBatch_GL11_ClampColor(void)
9388 if (!rsurface.passcolor4f)
9390 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9392 c2[0] = bound(0.0f, c1[0], 1.0f);
9393 c2[1] = bound(0.0f, c1[1], 1.0f);
9394 c2[2] = bound(0.0f, c1[2], 1.0f);
9395 c2[3] = bound(0.0f, c1[3], 1.0f);
9399 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9409 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9410 rsurface.passcolor4f_vertexbuffer = 0;
9411 rsurface.passcolor4f_bufferoffset = 0;
9412 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)
9414 f = -DotProduct(r_refdef.view.forward, n);
9416 f = f * 0.85 + 0.15; // work around so stuff won't get black
9417 f *= r_refdef.lightmapintensity;
9418 Vector4Set(c, f, f, f, 1);
9422 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9424 RSurf_DrawBatch_GL11_ApplyFakeLight();
9425 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9426 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9427 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9428 GL_Color(r, g, b, a);
9432 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9440 vec3_t ambientcolor;
9441 vec3_t diffusecolor;
9445 VectorCopy(rsurface.modellight_lightdir, lightdir);
9446 f = 0.5f * r_refdef.lightmapintensity;
9447 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9448 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9449 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9450 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9451 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9452 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9454 if (VectorLength2(diffusecolor) > 0)
9456 // q3-style directional shading
9457 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9458 rsurface.passcolor4f_vertexbuffer = 0;
9459 rsurface.passcolor4f_bufferoffset = 0;
9460 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)
9462 if ((f = DotProduct(n, lightdir)) > 0)
9463 VectorMA(ambientcolor, f, diffusecolor, c);
9465 VectorCopy(ambientcolor, c);
9472 *applycolor = false;
9476 *r = ambientcolor[0];
9477 *g = ambientcolor[1];
9478 *b = ambientcolor[2];
9479 rsurface.passcolor4f = NULL;
9480 rsurface.passcolor4f_vertexbuffer = 0;
9481 rsurface.passcolor4f_bufferoffset = 0;
9485 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9487 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9488 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9489 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9490 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9491 GL_Color(r, g, b, a);
9495 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9503 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9504 rsurface.passcolor4f_vertexbuffer = 0;
9505 rsurface.passcolor4f_bufferoffset = 0;
9507 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9509 f = 1 - RSurf_FogVertex(v);
9517 void RSurf_SetupDepthAndCulling(void)
9519 // submodels are biased to avoid z-fighting with world surfaces that they
9520 // may be exactly overlapping (avoids z-fighting artifacts on certain
9521 // doors and things in Quake maps)
9522 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9523 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9524 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9525 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9528 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9530 // transparent sky would be ridiculous
9531 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9533 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
9534 skyrenderlater = true;
9535 RSurf_SetupDepthAndCulling();
9537 // LordHavoc: HalfLife maps have freaky skypolys so don't use
9538 // skymasking on them, and Quake3 never did sky masking (unlike
9539 // software Quake and software Quake2), so disable the sky masking
9540 // in Quake3 maps as it causes problems with q3map2 sky tricks,
9541 // and skymasking also looks very bad when noclipping outside the
9542 // level, so don't use it then either.
9543 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
9545 R_Mesh_ResetTextureState();
9546 if (skyrendermasked)
9548 R_SetupShader_DepthOrShadow(false);
9549 // depth-only (masking)
9550 GL_ColorMask(0,0,0,0);
9551 // just to make sure that braindead drivers don't draw
9552 // anything despite that colormask...
9553 GL_BlendFunc(GL_ZERO, GL_ONE);
9554 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9555 if (rsurface.batchvertex3fbuffer)
9556 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9558 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9562 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
9564 GL_BlendFunc(GL_ONE, GL_ZERO);
9565 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9566 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9567 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9570 if (skyrendermasked)
9571 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9573 R_Mesh_ResetTextureState();
9574 GL_Color(1, 1, 1, 1);
9577 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9578 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9579 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9581 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9585 // render screenspace normalmap to texture
9587 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
9591 // bind lightmap texture
9593 // water/refraction/reflection/camera surfaces have to be handled specially
9594 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9596 int start, end, startplaneindex;
9597 for (start = 0;start < texturenumsurfaces;start = end)
9599 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9600 if(startplaneindex < 0)
9602 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9603 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9607 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9609 // now that we have a batch using the same planeindex, render it
9610 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9612 // render water or distortion background
9614 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);
9616 // blend surface on top
9617 GL_DepthMask(false);
9618 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
9621 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9623 // render surface with reflection texture as input
9624 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9625 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);
9632 // render surface batch normally
9633 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9634 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);
9635 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9638 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9639 GL_AlphaTest(false);
9642 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9644 // OpenGL 1.3 path - anything not completely ancient
9645 qboolean applycolor;
9648 const texturelayer_t *layer;
9649 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);
9650 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9652 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9655 int layertexrgbscale;
9656 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9658 if (layerindex == 0)
9662 GL_AlphaTest(false);
9663 GL_DepthFunc(GL_EQUAL);
9666 GL_DepthMask(layer->depthmask && writedepth);
9667 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9668 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9670 layertexrgbscale = 4;
9671 VectorScale(layer->color, 0.25f, layercolor);
9673 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9675 layertexrgbscale = 2;
9676 VectorScale(layer->color, 0.5f, layercolor);
9680 layertexrgbscale = 1;
9681 VectorScale(layer->color, 1.0f, layercolor);
9683 layercolor[3] = layer->color[3];
9684 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9685 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9686 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9687 switch (layer->type)
9689 case TEXTURELAYERTYPE_LITTEXTURE:
9690 // single-pass lightmapped texture with 2x rgbscale
9691 R_Mesh_TexBind(0, r_texture_white);
9692 R_Mesh_TexMatrix(0, NULL);
9693 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9694 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9695 R_Mesh_TexBind(1, layer->texture);
9696 R_Mesh_TexMatrix(1, &layer->texmatrix);
9697 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9698 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9699 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9700 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9701 else if (FAKELIGHT_ENABLED)
9702 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9703 else if (rsurface.uselightmaptexture)
9704 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9706 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9708 case TEXTURELAYERTYPE_TEXTURE:
9709 // singletexture unlit texture with transparency support
9710 R_Mesh_TexBind(0, layer->texture);
9711 R_Mesh_TexMatrix(0, &layer->texmatrix);
9712 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9713 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9714 R_Mesh_TexBind(1, 0);
9715 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9716 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9718 case TEXTURELAYERTYPE_FOG:
9719 // singletexture fogging
9722 R_Mesh_TexBind(0, layer->texture);
9723 R_Mesh_TexMatrix(0, &layer->texmatrix);
9724 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9725 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9729 R_Mesh_TexBind(0, 0);
9730 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9732 R_Mesh_TexBind(1, 0);
9733 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9734 // generate a color array for the fog pass
9735 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9736 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9740 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9743 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9745 GL_DepthFunc(GL_LEQUAL);
9746 GL_AlphaTest(false);
9750 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9752 // OpenGL 1.1 - crusty old voodoo path
9755 const texturelayer_t *layer;
9756 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);
9757 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9759 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9761 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9763 if (layerindex == 0)
9767 GL_AlphaTest(false);
9768 GL_DepthFunc(GL_EQUAL);
9771 GL_DepthMask(layer->depthmask && writedepth);
9772 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9773 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9774 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9775 switch (layer->type)
9777 case TEXTURELAYERTYPE_LITTEXTURE:
9778 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9780 // two-pass lit texture with 2x rgbscale
9781 // first the lightmap pass
9782 R_Mesh_TexBind(0, r_texture_white);
9783 R_Mesh_TexMatrix(0, NULL);
9784 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9785 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9786 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9787 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9788 else if (FAKELIGHT_ENABLED)
9789 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9790 else if (rsurface.uselightmaptexture)
9791 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9793 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9794 // then apply the texture to it
9795 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9796 R_Mesh_TexBind(0, layer->texture);
9797 R_Mesh_TexMatrix(0, &layer->texmatrix);
9798 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9799 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9800 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);
9804 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9805 R_Mesh_TexBind(0, layer->texture);
9806 R_Mesh_TexMatrix(0, &layer->texmatrix);
9807 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9808 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9809 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9810 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);
9812 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);
9815 case TEXTURELAYERTYPE_TEXTURE:
9816 // singletexture unlit texture with transparency support
9817 R_Mesh_TexBind(0, layer->texture);
9818 R_Mesh_TexMatrix(0, &layer->texmatrix);
9819 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9820 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9821 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);
9823 case TEXTURELAYERTYPE_FOG:
9824 // singletexture fogging
9827 R_Mesh_TexBind(0, layer->texture);
9828 R_Mesh_TexMatrix(0, &layer->texmatrix);
9829 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9830 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9834 R_Mesh_TexBind(0, 0);
9835 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9837 // generate a color array for the fog pass
9838 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9839 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9843 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9846 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9848 GL_DepthFunc(GL_LEQUAL);
9849 GL_AlphaTest(false);
9853 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9857 r_vertexgeneric_t *batchvertex;
9860 // R_Mesh_ResetTextureState();
9861 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
9863 if(rsurface.texture && rsurface.texture->currentskinframe)
9865 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9866 c[3] *= rsurface.texture->currentalpha;
9876 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9878 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9879 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9880 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9883 // brighten it up (as texture value 127 means "unlit")
9884 c[0] *= 2 * r_refdef.view.colorscale;
9885 c[1] *= 2 * r_refdef.view.colorscale;
9886 c[2] *= 2 * r_refdef.view.colorscale;
9888 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9889 c[3] *= r_wateralpha.value;
9891 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9893 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9894 GL_DepthMask(false);
9896 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9898 GL_BlendFunc(GL_ONE, GL_ONE);
9899 GL_DepthMask(false);
9901 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9903 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9904 GL_DepthMask(false);
9906 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9908 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9909 GL_DepthMask(false);
9913 GL_BlendFunc(GL_ONE, GL_ZERO);
9914 GL_DepthMask(writedepth);
9917 if (r_showsurfaces.integer == 3)
9919 rsurface.passcolor4f = NULL;
9921 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9923 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9925 rsurface.passcolor4f = NULL;
9926 rsurface.passcolor4f_vertexbuffer = 0;
9927 rsurface.passcolor4f_bufferoffset = 0;
9929 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9931 qboolean applycolor = true;
9934 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9936 r_refdef.lightmapintensity = 1;
9937 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9938 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9940 else if (FAKELIGHT_ENABLED)
9942 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9944 r_refdef.lightmapintensity = r_fakelight_intensity.value;
9945 RSurf_DrawBatch_GL11_ApplyFakeLight();
9946 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9950 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9952 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9953 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9954 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9957 if(!rsurface.passcolor4f)
9958 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9960 RSurf_DrawBatch_GL11_ApplyAmbient();
9961 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9962 if(r_refdef.fogenabled)
9963 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9964 RSurf_DrawBatch_GL11_ClampColor();
9966 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9967 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
9970 else if (!r_refdef.view.showdebug)
9972 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9973 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9974 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9976 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9977 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9979 R_Mesh_PrepareVertices_Generic_Unlock();
9982 else if (r_showsurfaces.integer == 4)
9984 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9985 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9986 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9988 unsigned char c = (vi << 3) * (1.0f / 256.0f);
9989 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9990 Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9992 R_Mesh_PrepareVertices_Generic_Unlock();
9995 else if (r_showsurfaces.integer == 2)
9998 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9999 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10000 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10002 unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10003 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10004 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10005 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10006 Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10007 Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10008 Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10010 R_Mesh_PrepareVertices_Generic_Unlock();
10011 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10015 int texturesurfaceindex;
10017 const msurface_t *surface;
10018 float surfacecolor4f[4];
10019 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10020 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10022 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10024 surface = texturesurfacelist[texturesurfaceindex];
10025 k = (int)(((size_t)surface) / sizeof(msurface_t));
10026 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10027 for (j = 0;j < surface->num_vertices;j++)
10029 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10030 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10034 R_Mesh_PrepareVertices_Generic_Unlock();
10039 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10042 RSurf_SetupDepthAndCulling();
10043 if (r_showsurfaces.integer)
10045 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10048 switch (vid.renderpath)
10050 case RENDERPATH_GL20:
10051 case RENDERPATH_D3D9:
10052 case RENDERPATH_D3D10:
10053 case RENDERPATH_D3D11:
10054 case RENDERPATH_SOFT:
10055 case RENDERPATH_GLES2:
10056 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10058 case RENDERPATH_GL13:
10059 case RENDERPATH_GLES1:
10060 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10062 case RENDERPATH_GL11:
10063 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10069 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10072 RSurf_SetupDepthAndCulling();
10073 if (r_showsurfaces.integer)
10075 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10078 switch (vid.renderpath)
10080 case RENDERPATH_GL20:
10081 case RENDERPATH_D3D9:
10082 case RENDERPATH_D3D10:
10083 case RENDERPATH_D3D11:
10084 case RENDERPATH_SOFT:
10085 case RENDERPATH_GLES2:
10086 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10088 case RENDERPATH_GL13:
10089 case RENDERPATH_GLES1:
10090 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10092 case RENDERPATH_GL11:
10093 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10099 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10102 int texturenumsurfaces, endsurface;
10103 texture_t *texture;
10104 const msurface_t *surface;
10105 const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10107 // if the model is static it doesn't matter what value we give for
10108 // wantnormals and wanttangents, so this logic uses only rules applicable
10109 // to a model, knowing that they are meaningless otherwise
10110 if (ent == r_refdef.scene.worldentity)
10111 RSurf_ActiveWorldEntity();
10112 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10113 RSurf_ActiveModelEntity(ent, false, false, false);
10116 switch (vid.renderpath)
10118 case RENDERPATH_GL20:
10119 case RENDERPATH_D3D9:
10120 case RENDERPATH_D3D10:
10121 case RENDERPATH_D3D11:
10122 case RENDERPATH_SOFT:
10123 case RENDERPATH_GLES2:
10124 RSurf_ActiveModelEntity(ent, true, true, false);
10126 case RENDERPATH_GL11:
10127 case RENDERPATH_GL13:
10128 case RENDERPATH_GLES1:
10129 RSurf_ActiveModelEntity(ent, true, false, false);
10134 if (r_transparentdepthmasking.integer)
10136 qboolean setup = false;
10137 for (i = 0;i < numsurfaces;i = j)
10140 surface = rsurface.modelsurfaces + surfacelist[i];
10141 texture = surface->texture;
10142 rsurface.texture = R_GetCurrentTexture(texture);
10143 rsurface.lightmaptexture = NULL;
10144 rsurface.deluxemaptexture = NULL;
10145 rsurface.uselightmaptexture = false;
10146 // scan ahead until we find a different texture
10147 endsurface = min(i + 1024, numsurfaces);
10148 texturenumsurfaces = 0;
10149 texturesurfacelist[texturenumsurfaces++] = surface;
10150 for (;j < endsurface;j++)
10152 surface = rsurface.modelsurfaces + surfacelist[j];
10153 if (texture != surface->texture)
10155 texturesurfacelist[texturenumsurfaces++] = surface;
10157 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10159 // render the range of surfaces as depth
10163 GL_ColorMask(0,0,0,0);
10165 GL_DepthTest(true);
10166 GL_BlendFunc(GL_ONE, GL_ZERO);
10167 GL_DepthMask(true);
10168 // R_Mesh_ResetTextureState();
10169 R_SetupShader_DepthOrShadow(false);
10171 RSurf_SetupDepthAndCulling();
10172 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10173 if (rsurface.batchvertex3fbuffer)
10174 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10176 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10180 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10183 for (i = 0;i < numsurfaces;i = j)
10186 surface = rsurface.modelsurfaces + surfacelist[i];
10187 texture = surface->texture;
10188 rsurface.texture = R_GetCurrentTexture(texture);
10189 // scan ahead until we find a different texture
10190 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10191 texturenumsurfaces = 0;
10192 texturesurfacelist[texturenumsurfaces++] = surface;
10193 if(FAKELIGHT_ENABLED)
10195 rsurface.lightmaptexture = NULL;
10196 rsurface.deluxemaptexture = NULL;
10197 rsurface.uselightmaptexture = false;
10198 for (;j < endsurface;j++)
10200 surface = rsurface.modelsurfaces + surfacelist[j];
10201 if (texture != surface->texture)
10203 texturesurfacelist[texturenumsurfaces++] = surface;
10208 rsurface.lightmaptexture = surface->lightmaptexture;
10209 rsurface.deluxemaptexture = surface->deluxemaptexture;
10210 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10211 for (;j < endsurface;j++)
10213 surface = rsurface.modelsurfaces + surfacelist[j];
10214 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10216 texturesurfacelist[texturenumsurfaces++] = surface;
10219 // render the range of surfaces
10220 if (ent == r_refdef.scene.worldentity)
10221 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10223 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10225 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10228 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10230 // transparent surfaces get pushed off into the transparent queue
10231 int surfacelistindex;
10232 const msurface_t *surface;
10233 vec3_t tempcenter, center;
10234 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10236 surface = texturesurfacelist[surfacelistindex];
10237 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10238 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10239 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10240 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10241 if (queueentity->transparent_offset) // transparent offset
10243 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10244 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10245 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10247 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10251 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10253 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10255 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10257 RSurf_SetupDepthAndCulling();
10258 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10259 if (rsurface.batchvertex3fbuffer)
10260 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10262 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10266 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10268 const entity_render_t *queueentity = r_refdef.scene.worldentity;
10271 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10274 if (!rsurface.texture->currentnumlayers)
10276 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10277 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10279 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10281 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10282 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10283 else if (!rsurface.texture->currentnumlayers)
10285 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10287 // in the deferred case, transparent surfaces were queued during prepass
10288 if (!r_shadow_usingdeferredprepass)
10289 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10293 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10294 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10299 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10302 texture_t *texture;
10303 R_FrameData_SetMark();
10304 // break the surface list down into batches by texture and use of lightmapping
10305 for (i = 0;i < numsurfaces;i = j)
10308 // texture is the base texture pointer, rsurface.texture is the
10309 // current frame/skin the texture is directing us to use (for example
10310 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10311 // use skin 1 instead)
10312 texture = surfacelist[i]->texture;
10313 rsurface.texture = R_GetCurrentTexture(texture);
10314 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10316 // if this texture is not the kind we want, skip ahead to the next one
10317 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10321 if(FAKELIGHT_ENABLED || depthonly || prepass)
10323 rsurface.lightmaptexture = NULL;
10324 rsurface.deluxemaptexture = NULL;
10325 rsurface.uselightmaptexture = false;
10326 // simply scan ahead until we find a different texture or lightmap state
10327 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10332 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10333 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10334 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10335 // simply scan ahead until we find a different texture or lightmap state
10336 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10339 // render the range of surfaces
10340 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10342 R_FrameData_ReturnToMark();
10345 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10349 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10352 if (!rsurface.texture->currentnumlayers)
10354 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10355 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10357 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10359 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10360 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10361 else if (!rsurface.texture->currentnumlayers)
10363 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10365 // in the deferred case, transparent surfaces were queued during prepass
10366 if (!r_shadow_usingdeferredprepass)
10367 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10371 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10372 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10377 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10380 texture_t *texture;
10381 R_FrameData_SetMark();
10382 // break the surface list down into batches by texture and use of lightmapping
10383 for (i = 0;i < numsurfaces;i = j)
10386 // texture is the base texture pointer, rsurface.texture is the
10387 // current frame/skin the texture is directing us to use (for example
10388 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10389 // use skin 1 instead)
10390 texture = surfacelist[i]->texture;
10391 rsurface.texture = R_GetCurrentTexture(texture);
10392 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10394 // if this texture is not the kind we want, skip ahead to the next one
10395 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10399 if(FAKELIGHT_ENABLED || depthonly || prepass)
10401 rsurface.lightmaptexture = NULL;
10402 rsurface.deluxemaptexture = NULL;
10403 rsurface.uselightmaptexture = false;
10404 // simply scan ahead until we find a different texture or lightmap state
10405 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10410 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10411 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10412 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10413 // simply scan ahead until we find a different texture or lightmap state
10414 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10417 // render the range of surfaces
10418 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10420 R_FrameData_ReturnToMark();
10423 float locboxvertex3f[6*4*3] =
10425 1,0,1, 1,0,0, 1,1,0, 1,1,1,
10426 0,1,1, 0,1,0, 0,0,0, 0,0,1,
10427 1,1,1, 1,1,0, 0,1,0, 0,1,1,
10428 0,0,1, 0,0,0, 1,0,0, 1,0,1,
10429 0,0,1, 1,0,1, 1,1,1, 0,1,1,
10430 1,0,0, 0,0,0, 0,1,0, 1,1,0
10433 unsigned short locboxelements[6*2*3] =
10438 12,13,14, 12,14,15,
10439 16,17,18, 16,18,19,
10443 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10446 cl_locnode_t *loc = (cl_locnode_t *)ent;
10448 float vertex3f[6*4*3];
10450 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10451 GL_DepthMask(false);
10452 GL_DepthRange(0, 1);
10453 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10454 GL_DepthTest(true);
10455 GL_CullFace(GL_NONE);
10456 R_EntityMatrix(&identitymatrix);
10458 // R_Mesh_ResetTextureState();
10460 i = surfacelist[0];
10461 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10462 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10463 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10464 surfacelist[0] < 0 ? 0.5f : 0.125f);
10466 if (VectorCompare(loc->mins, loc->maxs))
10468 VectorSet(size, 2, 2, 2);
10469 VectorMA(loc->mins, -0.5f, size, mins);
10473 VectorCopy(loc->mins, mins);
10474 VectorSubtract(loc->maxs, loc->mins, size);
10477 for (i = 0;i < 6*4*3;)
10478 for (j = 0;j < 3;j++, i++)
10479 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10481 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10482 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
10483 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10486 void R_DrawLocs(void)
10489 cl_locnode_t *loc, *nearestloc;
10491 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10492 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10494 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10495 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10499 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10501 if (decalsystem->decals)
10502 Mem_Free(decalsystem->decals);
10503 memset(decalsystem, 0, sizeof(*decalsystem));
10506 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)
10509 tridecal_t *decals;
10512 // expand or initialize the system
10513 if (decalsystem->maxdecals <= decalsystem->numdecals)
10515 decalsystem_t old = *decalsystem;
10516 qboolean useshortelements;
10517 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10518 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10519 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)));
10520 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10521 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10522 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10523 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10524 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10525 if (decalsystem->numdecals)
10526 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10528 Mem_Free(old.decals);
10529 for (i = 0;i < decalsystem->maxdecals*3;i++)
10530 decalsystem->element3i[i] = i;
10531 if (useshortelements)
10532 for (i = 0;i < decalsystem->maxdecals*3;i++)
10533 decalsystem->element3s[i] = i;
10536 // grab a decal and search for another free slot for the next one
10537 decals = decalsystem->decals;
10538 decal = decalsystem->decals + (i = decalsystem->freedecal++);
10539 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10541 decalsystem->freedecal = i;
10542 if (decalsystem->numdecals <= i)
10543 decalsystem->numdecals = i + 1;
10545 // initialize the decal
10547 decal->triangleindex = triangleindex;
10548 decal->surfaceindex = surfaceindex;
10549 decal->decalsequence = decalsequence;
10550 decal->color4f[0][0] = c0[0];
10551 decal->color4f[0][1] = c0[1];
10552 decal->color4f[0][2] = c0[2];
10553 decal->color4f[0][3] = 1;
10554 decal->color4f[1][0] = c1[0];
10555 decal->color4f[1][1] = c1[1];
10556 decal->color4f[1][2] = c1[2];
10557 decal->color4f[1][3] = 1;
10558 decal->color4f[2][0] = c2[0];
10559 decal->color4f[2][1] = c2[1];
10560 decal->color4f[2][2] = c2[2];
10561 decal->color4f[2][3] = 1;
10562 decal->vertex3f[0][0] = v0[0];
10563 decal->vertex3f[0][1] = v0[1];
10564 decal->vertex3f[0][2] = v0[2];
10565 decal->vertex3f[1][0] = v1[0];
10566 decal->vertex3f[1][1] = v1[1];
10567 decal->vertex3f[1][2] = v1[2];
10568 decal->vertex3f[2][0] = v2[0];
10569 decal->vertex3f[2][1] = v2[1];
10570 decal->vertex3f[2][2] = v2[2];
10571 decal->texcoord2f[0][0] = t0[0];
10572 decal->texcoord2f[0][1] = t0[1];
10573 decal->texcoord2f[1][0] = t1[0];
10574 decal->texcoord2f[1][1] = t1[1];
10575 decal->texcoord2f[2][0] = t2[0];
10576 decal->texcoord2f[2][1] = t2[1];
10577 TriangleNormal(v0, v1, v2, decal->plane);
10578 VectorNormalize(decal->plane);
10579 decal->plane[3] = DotProduct(v0, decal->plane);
10582 extern cvar_t cl_decals_bias;
10583 extern cvar_t cl_decals_models;
10584 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10585 // baseparms, parms, temps
10586 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)
10591 const float *vertex3f;
10592 const float *normal3f;
10594 float points[2][9][3];
10601 e = rsurface.modelelement3i + 3*triangleindex;
10603 vertex3f = rsurface.modelvertex3f;
10604 normal3f = rsurface.modelnormal3f;
10608 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10610 index = 3*e[cornerindex];
10611 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10616 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10618 index = 3*e[cornerindex];
10619 VectorCopy(vertex3f + index, v[cornerindex]);
10624 //TriangleNormal(v[0], v[1], v[2], normal);
10625 //if (DotProduct(normal, localnormal) < 0.0f)
10627 // clip by each of the box planes formed from the projection matrix
10628 // if anything survives, we emit the decal
10629 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]);
10632 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]);
10635 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]);
10638 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]);
10641 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]);
10644 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]);
10647 // some part of the triangle survived, so we have to accept it...
10650 // dynamic always uses the original triangle
10652 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10654 index = 3*e[cornerindex];
10655 VectorCopy(vertex3f + index, v[cornerindex]);
10658 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10660 // convert vertex positions to texcoords
10661 Matrix4x4_Transform(projection, v[cornerindex], temp);
10662 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10663 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10664 // calculate distance fade from the projection origin
10665 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10666 f = bound(0.0f, f, 1.0f);
10667 c[cornerindex][0] = r * f;
10668 c[cornerindex][1] = g * f;
10669 c[cornerindex][2] = b * f;
10670 c[cornerindex][3] = 1.0f;
10671 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10674 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);
10676 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10677 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);
10679 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)
10681 matrix4x4_t projection;
10682 decalsystem_t *decalsystem;
10685 const msurface_t *surface;
10686 const msurface_t *surfaces;
10687 const int *surfacelist;
10688 const texture_t *texture;
10690 int numsurfacelist;
10691 int surfacelistindex;
10694 float localorigin[3];
10695 float localnormal[3];
10696 float localmins[3];
10697 float localmaxs[3];
10700 float planes[6][4];
10703 int bih_triangles_count;
10704 int bih_triangles[256];
10705 int bih_surfaces[256];
10707 decalsystem = &ent->decalsystem;
10708 model = ent->model;
10709 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10711 R_DecalSystem_Reset(&ent->decalsystem);
10715 if (!model->brush.data_leafs && !cl_decals_models.integer)
10717 if (decalsystem->model)
10718 R_DecalSystem_Reset(decalsystem);
10722 if (decalsystem->model != model)
10723 R_DecalSystem_Reset(decalsystem);
10724 decalsystem->model = model;
10726 RSurf_ActiveModelEntity(ent, true, false, false);
10728 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10729 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10730 VectorNormalize(localnormal);
10731 localsize = worldsize*rsurface.inversematrixscale;
10732 localmins[0] = localorigin[0] - localsize;
10733 localmins[1] = localorigin[1] - localsize;
10734 localmins[2] = localorigin[2] - localsize;
10735 localmaxs[0] = localorigin[0] + localsize;
10736 localmaxs[1] = localorigin[1] + localsize;
10737 localmaxs[2] = localorigin[2] + localsize;
10739 //VectorCopy(localnormal, planes[4]);
10740 //VectorVectors(planes[4], planes[2], planes[0]);
10741 AnglesFromVectors(angles, localnormal, NULL, false);
10742 AngleVectors(angles, planes[0], planes[2], planes[4]);
10743 VectorNegate(planes[0], planes[1]);
10744 VectorNegate(planes[2], planes[3]);
10745 VectorNegate(planes[4], planes[5]);
10746 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10747 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10748 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10749 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10750 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10751 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10756 matrix4x4_t forwardprojection;
10757 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10758 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10763 float projectionvector[4][3];
10764 VectorScale(planes[0], ilocalsize, projectionvector[0]);
10765 VectorScale(planes[2], ilocalsize, projectionvector[1]);
10766 VectorScale(planes[4], ilocalsize, projectionvector[2]);
10767 projectionvector[0][0] = planes[0][0] * ilocalsize;
10768 projectionvector[0][1] = planes[1][0] * ilocalsize;
10769 projectionvector[0][2] = planes[2][0] * ilocalsize;
10770 projectionvector[1][0] = planes[0][1] * ilocalsize;
10771 projectionvector[1][1] = planes[1][1] * ilocalsize;
10772 projectionvector[1][2] = planes[2][1] * ilocalsize;
10773 projectionvector[2][0] = planes[0][2] * ilocalsize;
10774 projectionvector[2][1] = planes[1][2] * ilocalsize;
10775 projectionvector[2][2] = planes[2][2] * ilocalsize;
10776 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10777 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10778 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10779 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10783 dynamic = model->surfmesh.isanimated;
10784 numsurfacelist = model->nummodelsurfaces;
10785 surfacelist = model->sortedmodelsurfaces;
10786 surfaces = model->data_surfaces;
10789 bih_triangles_count = -1;
10792 if(model->render_bih.numleafs)
10793 bih = &model->render_bih;
10794 else if(model->collision_bih.numleafs)
10795 bih = &model->collision_bih;
10798 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10799 if(bih_triangles_count == 0)
10801 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10803 if(bih_triangles_count > 0)
10805 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10807 surfaceindex = bih_surfaces[triangleindex];
10808 surface = surfaces + surfaceindex;
10809 texture = surface->texture;
10810 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10812 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10814 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10819 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10821 surfaceindex = surfacelist[surfacelistindex];
10822 surface = surfaces + surfaceindex;
10823 // check cull box first because it rejects more than any other check
10824 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10826 // skip transparent surfaces
10827 texture = surface->texture;
10828 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10830 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10832 numtriangles = surface->num_triangles;
10833 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10834 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10839 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10840 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)
10842 int renderentityindex;
10843 float worldmins[3];
10844 float worldmaxs[3];
10845 entity_render_t *ent;
10847 if (!cl_decals_newsystem.integer)
10850 worldmins[0] = worldorigin[0] - worldsize;
10851 worldmins[1] = worldorigin[1] - worldsize;
10852 worldmins[2] = worldorigin[2] - worldsize;
10853 worldmaxs[0] = worldorigin[0] + worldsize;
10854 worldmaxs[1] = worldorigin[1] + worldsize;
10855 worldmaxs[2] = worldorigin[2] + worldsize;
10857 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10859 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10861 ent = r_refdef.scene.entities[renderentityindex];
10862 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10865 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10869 typedef struct r_decalsystem_splatqueue_s
10871 vec3_t worldorigin;
10872 vec3_t worldnormal;
10878 r_decalsystem_splatqueue_t;
10880 int r_decalsystem_numqueued = 0;
10881 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10883 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)
10885 r_decalsystem_splatqueue_t *queue;
10887 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10890 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10891 VectorCopy(worldorigin, queue->worldorigin);
10892 VectorCopy(worldnormal, queue->worldnormal);
10893 Vector4Set(queue->color, r, g, b, a);
10894 Vector4Set(queue->tcrange, s1, t1, s2, t2);
10895 queue->worldsize = worldsize;
10896 queue->decalsequence = cl.decalsequence++;
10899 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10902 r_decalsystem_splatqueue_t *queue;
10904 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10905 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);
10906 r_decalsystem_numqueued = 0;
10909 extern cvar_t cl_decals_max;
10910 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10913 decalsystem_t *decalsystem = &ent->decalsystem;
10920 if (!decalsystem->numdecals)
10923 if (r_showsurfaces.integer)
10926 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10928 R_DecalSystem_Reset(decalsystem);
10932 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10933 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10935 if (decalsystem->lastupdatetime)
10936 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
10939 decalsystem->lastupdatetime = r_refdef.scene.time;
10940 decal = decalsystem->decals;
10941 numdecals = decalsystem->numdecals;
10943 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10945 if (decal->color4f[0][3])
10947 decal->lived += frametime;
10948 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10950 memset(decal, 0, sizeof(*decal));
10951 if (decalsystem->freedecal > i)
10952 decalsystem->freedecal = i;
10956 decal = decalsystem->decals;
10957 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10960 // collapse the array by shuffling the tail decals into the gaps
10963 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10964 decalsystem->freedecal++;
10965 if (decalsystem->freedecal == numdecals)
10967 decal[decalsystem->freedecal] = decal[--numdecals];
10970 decalsystem->numdecals = numdecals;
10972 if (numdecals <= 0)
10974 // if there are no decals left, reset decalsystem
10975 R_DecalSystem_Reset(decalsystem);
10979 extern skinframe_t *decalskinframe;
10980 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10983 decalsystem_t *decalsystem = &ent->decalsystem;
10992 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10995 numdecals = decalsystem->numdecals;
10999 if (r_showsurfaces.integer)
11002 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11004 R_DecalSystem_Reset(decalsystem);
11008 // if the model is static it doesn't matter what value we give for
11009 // wantnormals and wanttangents, so this logic uses only rules applicable
11010 // to a model, knowing that they are meaningless otherwise
11011 if (ent == r_refdef.scene.worldentity)
11012 RSurf_ActiveWorldEntity();
11014 RSurf_ActiveModelEntity(ent, false, false, false);
11016 decalsystem->lastupdatetime = r_refdef.scene.time;
11017 decal = decalsystem->decals;
11019 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11021 // update vertex positions for animated models
11022 v3f = decalsystem->vertex3f;
11023 c4f = decalsystem->color4f;
11024 t2f = decalsystem->texcoord2f;
11025 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11027 if (!decal->color4f[0][3])
11030 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11034 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11037 // update color values for fading decals
11038 if (decal->lived >= cl_decals_time.value)
11039 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11043 c4f[ 0] = decal->color4f[0][0] * alpha;
11044 c4f[ 1] = decal->color4f[0][1] * alpha;
11045 c4f[ 2] = decal->color4f[0][2] * alpha;
11047 c4f[ 4] = decal->color4f[1][0] * alpha;
11048 c4f[ 5] = decal->color4f[1][1] * alpha;
11049 c4f[ 6] = decal->color4f[1][2] * alpha;
11051 c4f[ 8] = decal->color4f[2][0] * alpha;
11052 c4f[ 9] = decal->color4f[2][1] * alpha;
11053 c4f[10] = decal->color4f[2][2] * alpha;
11056 t2f[0] = decal->texcoord2f[0][0];
11057 t2f[1] = decal->texcoord2f[0][1];
11058 t2f[2] = decal->texcoord2f[1][0];
11059 t2f[3] = decal->texcoord2f[1][1];
11060 t2f[4] = decal->texcoord2f[2][0];
11061 t2f[5] = decal->texcoord2f[2][1];
11063 // update vertex positions for animated models
11064 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11066 e = rsurface.modelelement3i + 3*decal->triangleindex;
11067 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11068 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11069 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11073 VectorCopy(decal->vertex3f[0], v3f);
11074 VectorCopy(decal->vertex3f[1], v3f + 3);
11075 VectorCopy(decal->vertex3f[2], v3f + 6);
11078 if (r_refdef.fogenabled)
11080 alpha = RSurf_FogVertex(v3f);
11081 VectorScale(c4f, alpha, c4f);
11082 alpha = RSurf_FogVertex(v3f + 3);
11083 VectorScale(c4f + 4, alpha, c4f + 4);
11084 alpha = RSurf_FogVertex(v3f + 6);
11085 VectorScale(c4f + 8, alpha, c4f + 8);
11096 r_refdef.stats.drawndecals += numtris;
11098 // now render the decals all at once
11099 // (this assumes they all use one particle font texture!)
11100 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);
11101 // R_Mesh_ResetTextureState();
11102 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11103 GL_DepthMask(false);
11104 GL_DepthRange(0, 1);
11105 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11106 GL_DepthTest(true);
11107 GL_CullFace(GL_NONE);
11108 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11109 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false);
11110 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11114 static void R_DrawModelDecals(void)
11118 // fade faster when there are too many decals
11119 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11120 for (i = 0;i < r_refdef.scene.numentities;i++)
11121 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11123 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11124 for (i = 0;i < r_refdef.scene.numentities;i++)
11125 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11126 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11128 R_DecalSystem_ApplySplatEntitiesQueue();
11130 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11131 for (i = 0;i < r_refdef.scene.numentities;i++)
11132 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11134 r_refdef.stats.totaldecals += numdecals;
11136 if (r_showsurfaces.integer)
11139 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11141 for (i = 0;i < r_refdef.scene.numentities;i++)
11143 if (!r_refdef.viewcache.entityvisible[i])
11145 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11146 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11150 extern cvar_t mod_collision_bih;
11151 void R_DrawDebugModel(void)
11153 entity_render_t *ent = rsurface.entity;
11154 int i, j, k, l, flagsmask;
11155 const msurface_t *surface;
11156 dp_model_t *model = ent->model;
11159 if (!sv.active && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11162 if (r_showoverdraw.value > 0)
11164 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11165 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11166 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
11167 GL_DepthTest(false);
11168 GL_DepthMask(false);
11169 GL_DepthRange(0, 1);
11170 GL_BlendFunc(GL_ONE, GL_ONE);
11171 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11173 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11175 rsurface.texture = R_GetCurrentTexture(surface->texture);
11176 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11178 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11179 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11180 if (!rsurface.texture->currentlayers->depthmask)
11181 GL_Color(c, 0, 0, 1.0f);
11182 else if (ent == r_refdef.scene.worldentity)
11183 GL_Color(c, c, c, 1.0f);
11185 GL_Color(0, c, 0, 1.0f);
11186 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11190 rsurface.texture = NULL;
11193 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11195 // R_Mesh_ResetTextureState();
11196 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
11197 GL_DepthRange(0, 1);
11198 GL_DepthTest(!r_showdisabledepthtest.integer);
11199 GL_DepthMask(false);
11200 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11202 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11206 qboolean cullbox = ent == r_refdef.scene.worldentity;
11207 const q3mbrush_t *brush;
11208 const bih_t *bih = &model->collision_bih;
11209 const bih_leaf_t *bihleaf;
11210 float vertex3f[3][3];
11211 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11213 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11215 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11217 switch (bihleaf->type)
11220 brush = model->brush.data_brushes + bihleaf->itemindex;
11221 if (brush->colbrushf && brush->colbrushf->numtriangles)
11223 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);
11224 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11225 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11228 case BIH_COLLISIONTRIANGLE:
11229 triangleindex = bihleaf->itemindex;
11230 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11231 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11232 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11233 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);
11234 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11235 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11237 case BIH_RENDERTRIANGLE:
11238 triangleindex = bihleaf->itemindex;
11239 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11240 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11241 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11242 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);
11243 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11244 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11250 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11252 if (r_showtris.integer && qglPolygonMode)
11254 if (r_showdisabledepthtest.integer)
11256 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11257 GL_DepthMask(false);
11261 GL_BlendFunc(GL_ONE, GL_ZERO);
11262 GL_DepthMask(true);
11264 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11265 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11267 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11269 rsurface.texture = R_GetCurrentTexture(surface->texture);
11270 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11272 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11273 if (!rsurface.texture->currentlayers->depthmask)
11274 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11275 else if (ent == r_refdef.scene.worldentity)
11276 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11278 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11279 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11283 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11284 rsurface.texture = NULL;
11287 if (r_shownormals.value != 0 && qglBegin)
11289 if (r_showdisabledepthtest.integer)
11291 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11292 GL_DepthMask(false);
11296 GL_BlendFunc(GL_ONE, GL_ZERO);
11297 GL_DepthMask(true);
11299 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11301 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11303 rsurface.texture = R_GetCurrentTexture(surface->texture);
11304 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11306 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11307 qglBegin(GL_LINES);
11308 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11310 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11312 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11313 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11314 qglVertex3f(v[0], v[1], v[2]);
11315 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11316 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11317 qglVertex3f(v[0], v[1], v[2]);
11320 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11322 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11324 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11325 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11326 qglVertex3f(v[0], v[1], v[2]);
11327 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11328 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11329 qglVertex3f(v[0], v[1], v[2]);
11332 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11334 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11336 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11337 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11338 qglVertex3f(v[0], v[1], v[2]);
11339 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11340 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11341 qglVertex3f(v[0], v[1], v[2]);
11344 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11346 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11348 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11349 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11350 qglVertex3f(v[0], v[1], v[2]);
11351 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11352 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11353 qglVertex3f(v[0], v[1], v[2]);
11360 rsurface.texture = NULL;
11364 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11365 int r_maxsurfacelist = 0;
11366 const msurface_t **r_surfacelist = NULL;
11367 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11369 int i, j, endj, flagsmask;
11370 dp_model_t *model = r_refdef.scene.worldmodel;
11371 msurface_t *surfaces;
11372 unsigned char *update;
11373 int numsurfacelist = 0;
11377 if (r_maxsurfacelist < model->num_surfaces)
11379 r_maxsurfacelist = model->num_surfaces;
11381 Mem_Free((msurface_t**)r_surfacelist);
11382 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11385 RSurf_ActiveWorldEntity();
11387 surfaces = model->data_surfaces;
11388 update = model->brushq1.lightmapupdateflags;
11390 // update light styles on this submodel
11391 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11393 model_brush_lightstyleinfo_t *style;
11394 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11396 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11398 int *list = style->surfacelist;
11399 style->value = r_refdef.scene.lightstylevalue[style->style];
11400 for (j = 0;j < style->numsurfaces;j++)
11401 update[list[j]] = true;
11406 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11410 R_DrawDebugModel();
11411 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11415 rsurface.lightmaptexture = NULL;
11416 rsurface.deluxemaptexture = NULL;
11417 rsurface.uselightmaptexture = false;
11418 rsurface.texture = NULL;
11419 rsurface.rtlight = NULL;
11420 numsurfacelist = 0;
11421 // add visible surfaces to draw list
11422 for (i = 0;i < model->nummodelsurfaces;i++)
11424 j = model->sortedmodelsurfaces[i];
11425 if (r_refdef.viewcache.world_surfacevisible[j])
11426 r_surfacelist[numsurfacelist++] = surfaces + j;
11428 // update lightmaps if needed
11429 if (model->brushq1.firstrender)
11431 model->brushq1.firstrender = false;
11432 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11434 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11438 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11439 if (r_refdef.viewcache.world_surfacevisible[j])
11441 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11443 // don't do anything if there were no surfaces
11444 if (!numsurfacelist)
11446 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11449 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11451 // add to stats if desired
11452 if (r_speeds.integer && !skysurfaces && !depthonly)
11454 r_refdef.stats.world_surfaces += numsurfacelist;
11455 for (j = 0;j < numsurfacelist;j++)
11456 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11459 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11462 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11464 int i, j, endj, flagsmask;
11465 dp_model_t *model = ent->model;
11466 msurface_t *surfaces;
11467 unsigned char *update;
11468 int numsurfacelist = 0;
11472 if (r_maxsurfacelist < model->num_surfaces)
11474 r_maxsurfacelist = model->num_surfaces;
11476 Mem_Free((msurface_t **)r_surfacelist);
11477 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11480 // if the model is static it doesn't matter what value we give for
11481 // wantnormals and wanttangents, so this logic uses only rules applicable
11482 // to a model, knowing that they are meaningless otherwise
11483 if (ent == r_refdef.scene.worldentity)
11484 RSurf_ActiveWorldEntity();
11485 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11486 RSurf_ActiveModelEntity(ent, false, false, false);
11488 RSurf_ActiveModelEntity(ent, true, true, true);
11489 else if (depthonly)
11491 switch (vid.renderpath)
11493 case RENDERPATH_GL20:
11494 case RENDERPATH_D3D9:
11495 case RENDERPATH_D3D10:
11496 case RENDERPATH_D3D11:
11497 case RENDERPATH_SOFT:
11498 case RENDERPATH_GLES2:
11499 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11501 case RENDERPATH_GL11:
11502 case RENDERPATH_GL13:
11503 case RENDERPATH_GLES1:
11504 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11510 switch (vid.renderpath)
11512 case RENDERPATH_GL20:
11513 case RENDERPATH_D3D9:
11514 case RENDERPATH_D3D10:
11515 case RENDERPATH_D3D11:
11516 case RENDERPATH_SOFT:
11517 case RENDERPATH_GLES2:
11518 RSurf_ActiveModelEntity(ent, true, true, false);
11520 case RENDERPATH_GL11:
11521 case RENDERPATH_GL13:
11522 case RENDERPATH_GLES1:
11523 RSurf_ActiveModelEntity(ent, true, false, false);
11528 surfaces = model->data_surfaces;
11529 update = model->brushq1.lightmapupdateflags;
11531 // update light styles
11532 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11534 model_brush_lightstyleinfo_t *style;
11535 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11537 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11539 int *list = style->surfacelist;
11540 style->value = r_refdef.scene.lightstylevalue[style->style];
11541 for (j = 0;j < style->numsurfaces;j++)
11542 update[list[j]] = true;
11547 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11551 R_DrawDebugModel();
11552 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11556 rsurface.lightmaptexture = NULL;
11557 rsurface.deluxemaptexture = NULL;
11558 rsurface.uselightmaptexture = false;
11559 rsurface.texture = NULL;
11560 rsurface.rtlight = NULL;
11561 numsurfacelist = 0;
11562 // add visible surfaces to draw list
11563 for (i = 0;i < model->nummodelsurfaces;i++)
11564 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11565 // don't do anything if there were no surfaces
11566 if (!numsurfacelist)
11568 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11571 // update lightmaps if needed
11575 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11580 R_BuildLightMap(ent, surfaces + j);
11585 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11587 R_BuildLightMap(ent, surfaces + j);
11588 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11590 // add to stats if desired
11591 if (r_speeds.integer && !skysurfaces && !depthonly)
11593 r_refdef.stats.entities_surfaces += numsurfacelist;
11594 for (j = 0;j < numsurfacelist;j++)
11595 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11598 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11601 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11603 static texture_t texture;
11604 static msurface_t surface;
11605 const msurface_t *surfacelist = &surface;
11607 // fake enough texture and surface state to render this geometry
11609 texture.update_lastrenderframe = -1; // regenerate this texture
11610 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11611 texture.currentskinframe = skinframe;
11612 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11613 texture.offsetmapping = OFFSETMAPPING_OFF;
11614 texture.offsetscale = 1;
11615 texture.specularscalemod = 1;
11616 texture.specularpowermod = 1;
11618 surface.texture = &texture;
11619 surface.num_triangles = numtriangles;
11620 surface.num_firsttriangle = firsttriangle;
11621 surface.num_vertices = numvertices;
11622 surface.num_firstvertex = firstvertex;
11625 rsurface.texture = R_GetCurrentTexture(surface.texture);
11626 rsurface.lightmaptexture = NULL;
11627 rsurface.deluxemaptexture = NULL;
11628 rsurface.uselightmaptexture = false;
11629 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11632 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)
11634 static msurface_t surface;
11635 const msurface_t *surfacelist = &surface;
11637 // fake enough texture and surface state to render this geometry
11638 surface.texture = texture;
11639 surface.num_triangles = numtriangles;
11640 surface.num_firsttriangle = firsttriangle;
11641 surface.num_vertices = numvertices;
11642 surface.num_firstvertex = firstvertex;
11645 rsurface.texture = R_GetCurrentTexture(surface.texture);
11646 rsurface.lightmaptexture = NULL;
11647 rsurface.deluxemaptexture = NULL;
11648 rsurface.uselightmaptexture = false;
11649 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);