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", "1", "enables GL_ALPHA_TO_COVERAGE antialiasing technique on alphablend and alphatest surfaces when using vid_samples 2 or higher"};
76 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
77 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
78 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
79 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
80 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
81 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
82 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
83 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
84 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
85 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
86 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
87 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
88 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
89 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
90 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
91 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
92 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
93 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
94 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
95 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
96 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
97 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
98 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
99 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
101 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
102 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
103 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
105 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
106 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
107 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
108 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
109 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
110 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
111 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
112 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
113 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
114 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
115 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
116 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
117 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
118 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
119 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
120 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
121 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
122 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
123 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
124 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
125 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
126 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
128 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
129 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
130 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
131 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
132 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
133 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
134 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
135 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
137 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
138 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
140 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
141 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
142 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
144 cvar_t r_viewfbo = {CVAR_SAVE, "r_viewfbo", "0", "enables use of an 8bit (1) or 16bit (2) or 32bit (3) per component float framebuffer render, which may be at a different resolution than the video mode"};
145 cvar_t r_viewscale = {CVAR_SAVE, "r_viewscale", "1", "scaling factor for resolution of the fbo rendering method, must be > 0, can be above 1 for a costly antialiasing behavior, typical values are 0.5 for 1/4th as many pixels rendered, or 1 for normal rendering"};
146 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
147 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
148 cvar_t r_viewscale_fpsscaling_multiply = {CVAR_SAVE, "r_viewscale_fpsscaling_multiply", "5", "adjust quality up or down by the frametime difference from 1.0/target, multiplied by this factor"};
149 cvar_t r_viewscale_fpsscaling_stepsize = {CVAR_SAVE, "r_viewscale_fpsscaling_stepsize", "0.01", "smallest adjustment to hit the target framerate (this value prevents minute oscillations)"};
150 cvar_t r_viewscale_fpsscaling_stepmax = {CVAR_SAVE, "r_viewscale_fpsscaling_stepmax", "1.00", "largest adjustment to hit the target framerate (this value prevents wild overshooting of the estimate)"};
151 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
153 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
154 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
155 cvar_t r_glsl_offsetmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_steps", "2", "offset mapping steps (note: too high values may be not supported by your GPU)"};
156 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
157 cvar_t r_glsl_offsetmapping_reliefmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_steps", "10", "relief mapping steps (note: too high values may be not supported by your GPU)"};
158 cvar_t r_glsl_offsetmapping_reliefmapping_refinesteps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_refinesteps", "5", "relief mapping refine steps (these are a binary search executed as the last step as given by r_glsl_offsetmapping_reliefmapping_steps)"};
159 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
160 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
161 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
162 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
163 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
164 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
165 cvar_t r_glsl_postprocess_uservec1_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec1_enable", "1", "enables postprocessing uservec1 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
166 cvar_t r_glsl_postprocess_uservec2_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec2_enable", "1", "enables postprocessing uservec2 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
167 cvar_t r_glsl_postprocess_uservec3_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec3_enable", "1", "enables postprocessing uservec3 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
168 cvar_t r_glsl_postprocess_uservec4_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec4_enable", "1", "enables postprocessing uservec4 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
170 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
171 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
172 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
173 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
174 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
175 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
176 cvar_t r_water_lowquality = {0, "r_water_lowquality", "0", "special option to accelerate water rendering, 1 disables shadows and particles, 2 disables all dynamic lights"};
178 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
179 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
180 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
181 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
183 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
184 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
185 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
186 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
187 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
188 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
189 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
191 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
192 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
193 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
194 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivalent to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
195 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
196 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
197 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
198 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
199 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
200 cvar_t r_hdr_irisadaptation_fade = {CVAR_SAVE, "r_hdr_irisadaptation_fade", "1", "fade rate at which value adjusts"};
202 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
204 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
206 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
208 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
210 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
211 cvar_t r_glsl_saturation_redcompensate = {CVAR_SAVE, "r_glsl_saturation_redcompensate", "0", "a 'vampire sight' addition to desaturation effect, does compensation for red color, r_glsl_restart is required"};
213 cvar_t r_glsl_vertextextureblend_usebothalphas = {CVAR_SAVE, "r_glsl_vertextextureblend_usebothalphas", "0", "use both alpha layers on vertex blended surfaces, each alpha layer sets amount of 'blend leak' on another layer."};
215 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "0.5", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
217 extern cvar_t v_glslgamma;
219 extern qboolean v_flipped_state;
221 static struct r_bloomstate_s
226 int bloomwidth, bloomheight;
228 textype_t texturetype;
229 int viewfbo; // used to check if r_viewfbo cvar has changed
231 int fbo_framebuffer; // non-zero if r_viewfbo is enabled and working
232 rtexture_t *texture_framebuffercolor; // non-NULL if fbo_screen is non-zero
233 rtexture_t *texture_framebufferdepth; // non-NULL if fbo_screen is non-zero
235 int screentexturewidth, screentextureheight;
236 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
238 int bloomtexturewidth, bloomtextureheight;
239 rtexture_t *texture_bloom;
241 // arrays for rendering the screen passes
242 float screentexcoord2f[8];
243 float bloomtexcoord2f[8];
244 float offsettexcoord2f[8];
246 r_viewport_t viewport;
250 r_waterstate_t r_waterstate;
252 /// shadow volume bsp struct with automatically growing nodes buffer
255 rtexture_t *r_texture_blanknormalmap;
256 rtexture_t *r_texture_white;
257 rtexture_t *r_texture_grey128;
258 rtexture_t *r_texture_black;
259 rtexture_t *r_texture_notexture;
260 rtexture_t *r_texture_whitecube;
261 rtexture_t *r_texture_normalizationcube;
262 rtexture_t *r_texture_fogattenuation;
263 rtexture_t *r_texture_fogheighttexture;
264 rtexture_t *r_texture_gammaramps;
265 unsigned int r_texture_gammaramps_serial;
266 //rtexture_t *r_texture_fogintensity;
267 rtexture_t *r_texture_reflectcube;
269 // TODO: hash lookups?
270 typedef struct cubemapinfo_s
277 int r_texture_numcubemaps;
278 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
280 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
281 unsigned int r_numqueries;
282 unsigned int r_maxqueries;
284 typedef struct r_qwskincache_s
286 char name[MAX_QPATH];
287 skinframe_t *skinframe;
291 static r_qwskincache_t *r_qwskincache;
292 static int r_qwskincache_size;
294 /// vertex coordinates for a quad that covers the screen exactly
295 extern const float r_screenvertex3f[12];
296 extern const float r_d3dscreenvertex3f[12];
297 const float r_screenvertex3f[12] =
304 const float r_d3dscreenvertex3f[12] =
312 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
315 for (i = 0;i < verts;i++)
326 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
329 for (i = 0;i < verts;i++)
339 // FIXME: move this to client?
342 if (gamemode == GAME_NEHAHRA)
344 Cvar_Set("gl_fogenable", "0");
345 Cvar_Set("gl_fogdensity", "0.2");
346 Cvar_Set("gl_fogred", "0.3");
347 Cvar_Set("gl_foggreen", "0.3");
348 Cvar_Set("gl_fogblue", "0.3");
350 r_refdef.fog_density = 0;
351 r_refdef.fog_red = 0;
352 r_refdef.fog_green = 0;
353 r_refdef.fog_blue = 0;
354 r_refdef.fog_alpha = 1;
355 r_refdef.fog_start = 0;
356 r_refdef.fog_end = 16384;
357 r_refdef.fog_height = 1<<30;
358 r_refdef.fog_fadedepth = 128;
359 memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
362 static void R_BuildBlankTextures(void)
364 unsigned char data[4];
365 data[2] = 128; // normal X
366 data[1] = 128; // normal Y
367 data[0] = 255; // normal Z
368 data[3] = 128; // height
369 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
374 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
379 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
384 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
387 static void R_BuildNoTexture(void)
390 unsigned char pix[16][16][4];
391 // this makes a light grey/dark grey checkerboard texture
392 for (y = 0;y < 16;y++)
394 for (x = 0;x < 16;x++)
396 if ((y < 8) ^ (x < 8))
412 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
415 static void R_BuildWhiteCube(void)
417 unsigned char data[6*1*1*4];
418 memset(data, 255, sizeof(data));
419 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
422 static void R_BuildNormalizationCube(void)
426 vec_t s, t, intensity;
429 data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
430 for (side = 0;side < 6;side++)
432 for (y = 0;y < NORMSIZE;y++)
434 for (x = 0;x < NORMSIZE;x++)
436 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
437 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
472 intensity = 127.0f / sqrt(DotProduct(v, v));
473 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
474 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
475 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
476 data[((side*64+y)*64+x)*4+3] = 255;
480 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
484 static void R_BuildFogTexture(void)
488 unsigned char data1[FOGWIDTH][4];
489 //unsigned char data2[FOGWIDTH][4];
492 r_refdef.fogmasktable_start = r_refdef.fog_start;
493 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
494 r_refdef.fogmasktable_range = r_refdef.fogrange;
495 r_refdef.fogmasktable_density = r_refdef.fog_density;
497 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
498 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
500 d = (x * r - r_refdef.fogmasktable_start);
501 if(developer_extra.integer)
502 Con_DPrintf("%f ", d);
504 if (r_fog_exp2.integer)
505 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
507 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
508 if(developer_extra.integer)
509 Con_DPrintf(" : %f ", alpha);
510 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
511 if(developer_extra.integer)
512 Con_DPrintf(" = %f\n", alpha);
513 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
516 for (x = 0;x < FOGWIDTH;x++)
518 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
523 //data2[x][0] = 255 - b;
524 //data2[x][1] = 255 - b;
525 //data2[x][2] = 255 - b;
528 if (r_texture_fogattenuation)
530 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
531 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
535 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
536 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
540 static void R_BuildFogHeightTexture(void)
542 unsigned char *inpixels;
550 strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
551 if (r_refdef.fogheighttexturename[0])
552 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
555 r_refdef.fog_height_tablesize = 0;
556 if (r_texture_fogheighttexture)
557 R_FreeTexture(r_texture_fogheighttexture);
558 r_texture_fogheighttexture = NULL;
559 if (r_refdef.fog_height_table2d)
560 Mem_Free(r_refdef.fog_height_table2d);
561 r_refdef.fog_height_table2d = NULL;
562 if (r_refdef.fog_height_table1d)
563 Mem_Free(r_refdef.fog_height_table1d);
564 r_refdef.fog_height_table1d = NULL;
568 r_refdef.fog_height_tablesize = size;
569 r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
570 r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
571 memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
573 // LordHavoc: now the magic - what is that table2d for? it is a cooked
574 // average fog color table accounting for every fog layer between a point
575 // and the camera. (Note: attenuation is handled separately!)
576 for (y = 0;y < size;y++)
578 for (x = 0;x < size;x++)
584 for (j = x;j <= y;j++)
586 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
592 for (j = x;j >= y;j--)
594 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
599 r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
600 r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
601 r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
602 r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
605 r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
608 //=======================================================================================================================================================
610 static const char *builtinshaderstring =
611 #include "shader_glsl.h"
614 const char *builtinhlslshaderstring =
615 #include "shader_hlsl.h"
618 char *glslshaderstring = NULL;
619 char *hlslshaderstring = NULL;
621 //=======================================================================================================================================================
623 typedef struct shaderpermutationinfo_s
628 shaderpermutationinfo_t;
630 typedef struct shadermodeinfo_s
632 const char *vertexfilename;
633 const char *geometryfilename;
634 const char *fragmentfilename;
640 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
641 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
643 {"#define USEDIFFUSE\n", " diffuse"},
644 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
645 {"#define USEVIEWTINT\n", " viewtint"},
646 {"#define USECOLORMAPPING\n", " colormapping"},
647 {"#define USESATURATION\n", " saturation"},
648 {"#define USEFOGINSIDE\n", " foginside"},
649 {"#define USEFOGOUTSIDE\n", " fogoutside"},
650 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
651 {"#define USEFOGALPHAHACK\n", " fogalphahack"},
652 {"#define USEGAMMARAMPS\n", " gammaramps"},
653 {"#define USECUBEFILTER\n", " cubefilter"},
654 {"#define USEGLOW\n", " glow"},
655 {"#define USEBLOOM\n", " bloom"},
656 {"#define USESPECULAR\n", " specular"},
657 {"#define USEPOSTPROCESSING\n", " postprocessing"},
658 {"#define USEREFLECTION\n", " reflection"},
659 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
660 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
661 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
662 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
663 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
664 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
665 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
666 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
667 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
668 {"#define USEALPHAKILL\n", " alphakill"},
669 {"#define USEREFLECTCUBE\n", " reflectcube"},
670 {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
671 {"#define USEBOUNCEGRID\n", " bouncegrid"},
672 {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
673 {"#define USETRIPPY\n", " trippy"},
676 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
677 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
679 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
680 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
681 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
682 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
683 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
684 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
685 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
686 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
687 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
688 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
689 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
690 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
691 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
692 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
693 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
694 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
697 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
699 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
700 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
701 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
702 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
703 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
704 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
705 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
706 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
707 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
708 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
709 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
710 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
711 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
712 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
713 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
714 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
717 struct r_glsl_permutation_s;
718 typedef struct r_glsl_permutation_s
721 struct r_glsl_permutation_s *hashnext;
723 unsigned int permutation;
725 /// indicates if we have tried compiling this permutation already
727 /// 0 if compilation failed
729 // texture units assigned to each detected uniform
730 int tex_Texture_First;
731 int tex_Texture_Second;
732 int tex_Texture_GammaRamps;
733 int tex_Texture_Normal;
734 int tex_Texture_Color;
735 int tex_Texture_Gloss;
736 int tex_Texture_Glow;
737 int tex_Texture_SecondaryNormal;
738 int tex_Texture_SecondaryColor;
739 int tex_Texture_SecondaryGloss;
740 int tex_Texture_SecondaryGlow;
741 int tex_Texture_Pants;
742 int tex_Texture_Shirt;
743 int tex_Texture_FogHeightTexture;
744 int tex_Texture_FogMask;
745 int tex_Texture_Lightmap;
746 int tex_Texture_Deluxemap;
747 int tex_Texture_Attenuation;
748 int tex_Texture_Cube;
749 int tex_Texture_Refraction;
750 int tex_Texture_Reflection;
751 int tex_Texture_ShadowMap2D;
752 int tex_Texture_CubeProjection;
753 int tex_Texture_ScreenDepth;
754 int tex_Texture_ScreenNormalMap;
755 int tex_Texture_ScreenDiffuse;
756 int tex_Texture_ScreenSpecular;
757 int tex_Texture_ReflectMask;
758 int tex_Texture_ReflectCube;
759 int tex_Texture_BounceGrid;
760 /// locations of detected uniforms in program object, or -1 if not found
761 int loc_Texture_First;
762 int loc_Texture_Second;
763 int loc_Texture_GammaRamps;
764 int loc_Texture_Normal;
765 int loc_Texture_Color;
766 int loc_Texture_Gloss;
767 int loc_Texture_Glow;
768 int loc_Texture_SecondaryNormal;
769 int loc_Texture_SecondaryColor;
770 int loc_Texture_SecondaryGloss;
771 int loc_Texture_SecondaryGlow;
772 int loc_Texture_Pants;
773 int loc_Texture_Shirt;
774 int loc_Texture_FogHeightTexture;
775 int loc_Texture_FogMask;
776 int loc_Texture_Lightmap;
777 int loc_Texture_Deluxemap;
778 int loc_Texture_Attenuation;
779 int loc_Texture_Cube;
780 int loc_Texture_Refraction;
781 int loc_Texture_Reflection;
782 int loc_Texture_ShadowMap2D;
783 int loc_Texture_CubeProjection;
784 int loc_Texture_ScreenDepth;
785 int loc_Texture_ScreenNormalMap;
786 int loc_Texture_ScreenDiffuse;
787 int loc_Texture_ScreenSpecular;
788 int loc_Texture_ReflectMask;
789 int loc_Texture_ReflectCube;
790 int loc_Texture_BounceGrid;
792 int loc_BloomBlur_Parameters;
794 int loc_Color_Ambient;
795 int loc_Color_Diffuse;
796 int loc_Color_Specular;
800 int loc_DeferredColor_Ambient;
801 int loc_DeferredColor_Diffuse;
802 int loc_DeferredColor_Specular;
803 int loc_DeferredMod_Diffuse;
804 int loc_DeferredMod_Specular;
805 int loc_DistortScaleRefractReflect;
808 int loc_FogHeightFade;
810 int loc_FogPlaneViewDist;
811 int loc_FogRangeRecip;
814 int loc_LightPosition;
815 int loc_OffsetMapping_ScaleSteps;
817 int loc_ReflectColor;
818 int loc_ReflectFactor;
819 int loc_ReflectOffset;
820 int loc_RefractColor;
822 int loc_ScreenCenterRefractReflect;
823 int loc_ScreenScaleRefractReflect;
824 int loc_ScreenToDepth;
825 int loc_ShadowMap_Parameters;
826 int loc_ShadowMap_TextureScale;
827 int loc_SpecularPower;
832 int loc_ViewTintColor;
834 int loc_ModelToLight;
836 int loc_BackgroundTexMatrix;
837 int loc_ModelViewProjectionMatrix;
838 int loc_ModelViewMatrix;
839 int loc_PixelToScreenTexCoord;
840 int loc_ModelToReflectCube;
841 int loc_ShadowMapMatrix;
842 int loc_BloomColorSubtract;
843 int loc_NormalmapScrollBlend;
844 int loc_BounceGridMatrix;
845 int loc_BounceGridIntensity;
847 r_glsl_permutation_t;
849 #define SHADERPERMUTATION_HASHSIZE 256
852 // non-degradable "lightweight" shader parameters to keep the permutations simpler
853 // these can NOT degrade! only use for simple stuff
856 SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
857 SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
858 SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
859 SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
860 SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
861 SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5, ///< postprocess uservec4 is enabled
862 SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6 // use both alpha layers while blending materials, allows more advanced microblending
864 #define SHADERSTATICPARMS_COUNT 7
866 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
867 static int shaderstaticparms_count = 0;
869 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
870 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
871 qboolean R_CompileShader_CheckStaticParms(void)
873 static int r_compileshader_staticparms_save[1];
874 memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
875 memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
878 if (r_glsl_saturation_redcompensate.integer)
879 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
880 if (r_glsl_vertextextureblend_usebothalphas.integer)
881 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
882 if (r_shadow_glossexact.integer)
883 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
884 if (r_glsl_postprocess.integer)
886 if (r_glsl_postprocess_uservec1_enable.integer)
887 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
888 if (r_glsl_postprocess_uservec2_enable.integer)
889 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
890 if (r_glsl_postprocess_uservec3_enable.integer)
891 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
892 if (r_glsl_postprocess_uservec4_enable.integer)
893 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
895 return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
898 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
899 if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
900 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
902 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
903 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
905 shaderstaticparms_count = 0;
908 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
909 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
910 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
911 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
912 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
913 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
914 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
917 /// information about each possible shader permutation
918 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
919 /// currently selected permutation
920 r_glsl_permutation_t *r_glsl_permutation;
921 /// storage for permutations linked in the hash table
922 memexpandablearray_t r_glsl_permutationarray;
924 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
926 //unsigned int hashdepth = 0;
927 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
928 r_glsl_permutation_t *p;
929 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
931 if (p->mode == mode && p->permutation == permutation)
933 //if (hashdepth > 10)
934 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
939 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
941 p->permutation = permutation;
942 p->hashnext = r_glsl_permutationhash[mode][hashindex];
943 r_glsl_permutationhash[mode][hashindex] = p;
944 //if (hashdepth > 10)
945 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
949 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
952 if (!filename || !filename[0])
954 if (!strcmp(filename, "glsl/default.glsl"))
956 if (!glslshaderstring)
958 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
959 if (glslshaderstring)
960 Con_DPrintf("Loading shaders from file %s...\n", filename);
962 glslshaderstring = (char *)builtinshaderstring;
964 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
965 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
968 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
971 if (printfromdisknotice)
972 Con_DPrintf("from disk %s... ", filename);
978 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
982 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
983 char *vertexstring, *geometrystring, *fragmentstring;
984 char permutationname[256];
985 int vertstrings_count = 0;
986 int geomstrings_count = 0;
987 int fragstrings_count = 0;
988 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
989 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
990 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
997 permutationname[0] = 0;
998 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
999 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1000 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1002 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1004 // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1005 if(vid.support.gl20shaders130)
1007 vertstrings_list[vertstrings_count++] = "#version 130\n";
1008 geomstrings_list[geomstrings_count++] = "#version 130\n";
1009 fragstrings_list[fragstrings_count++] = "#version 130\n";
1010 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1011 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1012 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1015 // the first pretext is which type of shader to compile as
1016 // (later these will all be bound together as a program object)
1017 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1018 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1019 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1021 // the second pretext is the mode (for example a light source)
1022 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1023 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1024 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1025 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1027 // now add all the permutation pretexts
1028 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1030 if (permutation & (1<<i))
1032 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1033 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1034 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1035 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1039 // keep line numbers correct
1040 vertstrings_list[vertstrings_count++] = "\n";
1041 geomstrings_list[geomstrings_count++] = "\n";
1042 fragstrings_list[fragstrings_count++] = "\n";
1047 R_CompileShader_AddStaticParms(mode, permutation);
1048 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1049 vertstrings_count += shaderstaticparms_count;
1050 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1051 geomstrings_count += shaderstaticparms_count;
1052 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1053 fragstrings_count += shaderstaticparms_count;
1055 // now append the shader text itself
1056 vertstrings_list[vertstrings_count++] = vertexstring;
1057 geomstrings_list[geomstrings_count++] = geometrystring;
1058 fragstrings_list[fragstrings_count++] = fragmentstring;
1060 // if any sources were NULL, clear the respective list
1062 vertstrings_count = 0;
1063 if (!geometrystring)
1064 geomstrings_count = 0;
1065 if (!fragmentstring)
1066 fragstrings_count = 0;
1068 // compile the shader program
1069 if (vertstrings_count + geomstrings_count + fragstrings_count)
1070 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1074 qglUseProgram(p->program);CHECKGLERROR
1075 // look up all the uniform variable names we care about, so we don't
1076 // have to look them up every time we set them
1078 p->loc_Texture_First = qglGetUniformLocation(p->program, "Texture_First");
1079 p->loc_Texture_Second = qglGetUniformLocation(p->program, "Texture_Second");
1080 p->loc_Texture_GammaRamps = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1081 p->loc_Texture_Normal = qglGetUniformLocation(p->program, "Texture_Normal");
1082 p->loc_Texture_Color = qglGetUniformLocation(p->program, "Texture_Color");
1083 p->loc_Texture_Gloss = qglGetUniformLocation(p->program, "Texture_Gloss");
1084 p->loc_Texture_Glow = qglGetUniformLocation(p->program, "Texture_Glow");
1085 p->loc_Texture_SecondaryNormal = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1086 p->loc_Texture_SecondaryColor = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1087 p->loc_Texture_SecondaryGloss = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1088 p->loc_Texture_SecondaryGlow = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1089 p->loc_Texture_Pants = qglGetUniformLocation(p->program, "Texture_Pants");
1090 p->loc_Texture_Shirt = qglGetUniformLocation(p->program, "Texture_Shirt");
1091 p->loc_Texture_FogHeightTexture = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1092 p->loc_Texture_FogMask = qglGetUniformLocation(p->program, "Texture_FogMask");
1093 p->loc_Texture_Lightmap = qglGetUniformLocation(p->program, "Texture_Lightmap");
1094 p->loc_Texture_Deluxemap = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1095 p->loc_Texture_Attenuation = qglGetUniformLocation(p->program, "Texture_Attenuation");
1096 p->loc_Texture_Cube = qglGetUniformLocation(p->program, "Texture_Cube");
1097 p->loc_Texture_Refraction = qglGetUniformLocation(p->program, "Texture_Refraction");
1098 p->loc_Texture_Reflection = qglGetUniformLocation(p->program, "Texture_Reflection");
1099 p->loc_Texture_ShadowMap2D = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1100 p->loc_Texture_CubeProjection = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1101 p->loc_Texture_ScreenDepth = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1102 p->loc_Texture_ScreenNormalMap = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1103 p->loc_Texture_ScreenDiffuse = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1104 p->loc_Texture_ScreenSpecular = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1105 p->loc_Texture_ReflectMask = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1106 p->loc_Texture_ReflectCube = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1107 p->loc_Texture_BounceGrid = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1108 p->loc_Alpha = qglGetUniformLocation(p->program, "Alpha");
1109 p->loc_BloomBlur_Parameters = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1110 p->loc_ClientTime = qglGetUniformLocation(p->program, "ClientTime");
1111 p->loc_Color_Ambient = qglGetUniformLocation(p->program, "Color_Ambient");
1112 p->loc_Color_Diffuse = qglGetUniformLocation(p->program, "Color_Diffuse");
1113 p->loc_Color_Specular = qglGetUniformLocation(p->program, "Color_Specular");
1114 p->loc_Color_Glow = qglGetUniformLocation(p->program, "Color_Glow");
1115 p->loc_Color_Pants = qglGetUniformLocation(p->program, "Color_Pants");
1116 p->loc_Color_Shirt = qglGetUniformLocation(p->program, "Color_Shirt");
1117 p->loc_DeferredColor_Ambient = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1118 p->loc_DeferredColor_Diffuse = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1119 p->loc_DeferredColor_Specular = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1120 p->loc_DeferredMod_Diffuse = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1121 p->loc_DeferredMod_Specular = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1122 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1123 p->loc_EyePosition = qglGetUniformLocation(p->program, "EyePosition");
1124 p->loc_FogColor = qglGetUniformLocation(p->program, "FogColor");
1125 p->loc_FogHeightFade = qglGetUniformLocation(p->program, "FogHeightFade");
1126 p->loc_FogPlane = qglGetUniformLocation(p->program, "FogPlane");
1127 p->loc_FogPlaneViewDist = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1128 p->loc_FogRangeRecip = qglGetUniformLocation(p->program, "FogRangeRecip");
1129 p->loc_LightColor = qglGetUniformLocation(p->program, "LightColor");
1130 p->loc_LightDir = qglGetUniformLocation(p->program, "LightDir");
1131 p->loc_LightPosition = qglGetUniformLocation(p->program, "LightPosition");
1132 p->loc_OffsetMapping_ScaleSteps = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1133 p->loc_PixelSize = qglGetUniformLocation(p->program, "PixelSize");
1134 p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor");
1135 p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor");
1136 p->loc_ReflectOffset = qglGetUniformLocation(p->program, "ReflectOffset");
1137 p->loc_RefractColor = qglGetUniformLocation(p->program, "RefractColor");
1138 p->loc_Saturation = qglGetUniformLocation(p->program, "Saturation");
1139 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1140 p->loc_ScreenScaleRefractReflect = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1141 p->loc_ScreenToDepth = qglGetUniformLocation(p->program, "ScreenToDepth");
1142 p->loc_ShadowMap_Parameters = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1143 p->loc_ShadowMap_TextureScale = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1144 p->loc_SpecularPower = qglGetUniformLocation(p->program, "SpecularPower");
1145 p->loc_UserVec1 = qglGetUniformLocation(p->program, "UserVec1");
1146 p->loc_UserVec2 = qglGetUniformLocation(p->program, "UserVec2");
1147 p->loc_UserVec3 = qglGetUniformLocation(p->program, "UserVec3");
1148 p->loc_UserVec4 = qglGetUniformLocation(p->program, "UserVec4");
1149 p->loc_ViewTintColor = qglGetUniformLocation(p->program, "ViewTintColor");
1150 p->loc_ViewToLight = qglGetUniformLocation(p->program, "ViewToLight");
1151 p->loc_ModelToLight = qglGetUniformLocation(p->program, "ModelToLight");
1152 p->loc_TexMatrix = qglGetUniformLocation(p->program, "TexMatrix");
1153 p->loc_BackgroundTexMatrix = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1154 p->loc_ModelViewMatrix = qglGetUniformLocation(p->program, "ModelViewMatrix");
1155 p->loc_ModelViewProjectionMatrix = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1156 p->loc_PixelToScreenTexCoord = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1157 p->loc_ModelToReflectCube = qglGetUniformLocation(p->program, "ModelToReflectCube");
1158 p->loc_ShadowMapMatrix = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1159 p->loc_BloomColorSubtract = qglGetUniformLocation(p->program, "BloomColorSubtract");
1160 p->loc_NormalmapScrollBlend = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1161 p->loc_BounceGridMatrix = qglGetUniformLocation(p->program, "BounceGridMatrix");
1162 p->loc_BounceGridIntensity = qglGetUniformLocation(p->program, "BounceGridIntensity");
1163 // initialize the samplers to refer to the texture units we use
1164 p->tex_Texture_First = -1;
1165 p->tex_Texture_Second = -1;
1166 p->tex_Texture_GammaRamps = -1;
1167 p->tex_Texture_Normal = -1;
1168 p->tex_Texture_Color = -1;
1169 p->tex_Texture_Gloss = -1;
1170 p->tex_Texture_Glow = -1;
1171 p->tex_Texture_SecondaryNormal = -1;
1172 p->tex_Texture_SecondaryColor = -1;
1173 p->tex_Texture_SecondaryGloss = -1;
1174 p->tex_Texture_SecondaryGlow = -1;
1175 p->tex_Texture_Pants = -1;
1176 p->tex_Texture_Shirt = -1;
1177 p->tex_Texture_FogHeightTexture = -1;
1178 p->tex_Texture_FogMask = -1;
1179 p->tex_Texture_Lightmap = -1;
1180 p->tex_Texture_Deluxemap = -1;
1181 p->tex_Texture_Attenuation = -1;
1182 p->tex_Texture_Cube = -1;
1183 p->tex_Texture_Refraction = -1;
1184 p->tex_Texture_Reflection = -1;
1185 p->tex_Texture_ShadowMap2D = -1;
1186 p->tex_Texture_CubeProjection = -1;
1187 p->tex_Texture_ScreenDepth = -1;
1188 p->tex_Texture_ScreenNormalMap = -1;
1189 p->tex_Texture_ScreenDiffuse = -1;
1190 p->tex_Texture_ScreenSpecular = -1;
1191 p->tex_Texture_ReflectMask = -1;
1192 p->tex_Texture_ReflectCube = -1;
1193 p->tex_Texture_BounceGrid = -1;
1195 if (p->loc_Texture_First >= 0) {p->tex_Texture_First = sampler;qglUniform1i(p->loc_Texture_First , sampler);sampler++;}
1196 if (p->loc_Texture_Second >= 0) {p->tex_Texture_Second = sampler;qglUniform1i(p->loc_Texture_Second , sampler);sampler++;}
1197 if (p->loc_Texture_GammaRamps >= 0) {p->tex_Texture_GammaRamps = sampler;qglUniform1i(p->loc_Texture_GammaRamps , sampler);sampler++;}
1198 if (p->loc_Texture_Normal >= 0) {p->tex_Texture_Normal = sampler;qglUniform1i(p->loc_Texture_Normal , sampler);sampler++;}
1199 if (p->loc_Texture_Color >= 0) {p->tex_Texture_Color = sampler;qglUniform1i(p->loc_Texture_Color , sampler);sampler++;}
1200 if (p->loc_Texture_Gloss >= 0) {p->tex_Texture_Gloss = sampler;qglUniform1i(p->loc_Texture_Gloss , sampler);sampler++;}
1201 if (p->loc_Texture_Glow >= 0) {p->tex_Texture_Glow = sampler;qglUniform1i(p->loc_Texture_Glow , sampler);sampler++;}
1202 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1203 if (p->loc_Texture_SecondaryColor >= 0) {p->tex_Texture_SecondaryColor = sampler;qglUniform1i(p->loc_Texture_SecondaryColor , sampler);sampler++;}
1204 if (p->loc_Texture_SecondaryGloss >= 0) {p->tex_Texture_SecondaryGloss = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss , sampler);sampler++;}
1205 if (p->loc_Texture_SecondaryGlow >= 0) {p->tex_Texture_SecondaryGlow = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow , sampler);sampler++;}
1206 if (p->loc_Texture_Pants >= 0) {p->tex_Texture_Pants = sampler;qglUniform1i(p->loc_Texture_Pants , sampler);sampler++;}
1207 if (p->loc_Texture_Shirt >= 0) {p->tex_Texture_Shirt = sampler;qglUniform1i(p->loc_Texture_Shirt , sampler);sampler++;}
1208 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1209 if (p->loc_Texture_FogMask >= 0) {p->tex_Texture_FogMask = sampler;qglUniform1i(p->loc_Texture_FogMask , sampler);sampler++;}
1210 if (p->loc_Texture_Lightmap >= 0) {p->tex_Texture_Lightmap = sampler;qglUniform1i(p->loc_Texture_Lightmap , sampler);sampler++;}
1211 if (p->loc_Texture_Deluxemap >= 0) {p->tex_Texture_Deluxemap = sampler;qglUniform1i(p->loc_Texture_Deluxemap , sampler);sampler++;}
1212 if (p->loc_Texture_Attenuation >= 0) {p->tex_Texture_Attenuation = sampler;qglUniform1i(p->loc_Texture_Attenuation , sampler);sampler++;}
1213 if (p->loc_Texture_Cube >= 0) {p->tex_Texture_Cube = sampler;qglUniform1i(p->loc_Texture_Cube , sampler);sampler++;}
1214 if (p->loc_Texture_Refraction >= 0) {p->tex_Texture_Refraction = sampler;qglUniform1i(p->loc_Texture_Refraction , sampler);sampler++;}
1215 if (p->loc_Texture_Reflection >= 0) {p->tex_Texture_Reflection = sampler;qglUniform1i(p->loc_Texture_Reflection , sampler);sampler++;}
1216 if (p->loc_Texture_ShadowMap2D >= 0) {p->tex_Texture_ShadowMap2D = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D , sampler);sampler++;}
1217 if (p->loc_Texture_CubeProjection >= 0) {p->tex_Texture_CubeProjection = sampler;qglUniform1i(p->loc_Texture_CubeProjection , sampler);sampler++;}
1218 if (p->loc_Texture_ScreenDepth >= 0) {p->tex_Texture_ScreenDepth = sampler;qglUniform1i(p->loc_Texture_ScreenDepth , sampler);sampler++;}
1219 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1220 if (p->loc_Texture_ScreenDiffuse >= 0) {p->tex_Texture_ScreenDiffuse = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse , sampler);sampler++;}
1221 if (p->loc_Texture_ScreenSpecular >= 0) {p->tex_Texture_ScreenSpecular = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular , sampler);sampler++;}
1222 if (p->loc_Texture_ReflectMask >= 0) {p->tex_Texture_ReflectMask = sampler;qglUniform1i(p->loc_Texture_ReflectMask , sampler);sampler++;}
1223 if (p->loc_Texture_ReflectCube >= 0) {p->tex_Texture_ReflectCube = sampler;qglUniform1i(p->loc_Texture_ReflectCube , sampler);sampler++;}
1224 if (p->loc_Texture_BounceGrid >= 0) {p->tex_Texture_BounceGrid = sampler;qglUniform1i(p->loc_Texture_BounceGrid , sampler);sampler++;}
1226 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1229 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
1233 Mem_Free(vertexstring);
1235 Mem_Free(geometrystring);
1237 Mem_Free(fragmentstring);
1240 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1242 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1243 if (r_glsl_permutation != perm)
1245 r_glsl_permutation = perm;
1246 if (!r_glsl_permutation->program)
1248 if (!r_glsl_permutation->compiled)
1249 R_GLSL_CompilePermutation(perm, mode, permutation);
1250 if (!r_glsl_permutation->program)
1252 // remove features until we find a valid permutation
1254 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1256 // reduce i more quickly whenever it would not remove any bits
1257 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1258 if (!(permutation & j))
1261 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1262 if (!r_glsl_permutation->compiled)
1263 R_GLSL_CompilePermutation(perm, mode, permutation);
1264 if (r_glsl_permutation->program)
1267 if (i >= SHADERPERMUTATION_COUNT)
1269 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1270 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1271 qglUseProgram(0);CHECKGLERROR
1272 return; // no bit left to clear, entire mode is broken
1277 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1279 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1280 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1281 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1288 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1289 extern D3DCAPS9 vid_d3d9caps;
1292 struct r_hlsl_permutation_s;
1293 typedef struct r_hlsl_permutation_s
1295 /// hash lookup data
1296 struct r_hlsl_permutation_s *hashnext;
1298 unsigned int permutation;
1300 /// indicates if we have tried compiling this permutation already
1302 /// NULL if compilation failed
1303 IDirect3DVertexShader9 *vertexshader;
1304 IDirect3DPixelShader9 *pixelshader;
1306 r_hlsl_permutation_t;
1308 typedef enum D3DVSREGISTER_e
1310 D3DVSREGISTER_TexMatrix = 0, // float4x4
1311 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1312 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1313 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1314 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1315 D3DVSREGISTER_ModelToLight = 20, // float4x4
1316 D3DVSREGISTER_EyePosition = 24,
1317 D3DVSREGISTER_FogPlane = 25,
1318 D3DVSREGISTER_LightDir = 26,
1319 D3DVSREGISTER_LightPosition = 27,
1323 typedef enum D3DPSREGISTER_e
1325 D3DPSREGISTER_Alpha = 0,
1326 D3DPSREGISTER_BloomBlur_Parameters = 1,
1327 D3DPSREGISTER_ClientTime = 2,
1328 D3DPSREGISTER_Color_Ambient = 3,
1329 D3DPSREGISTER_Color_Diffuse = 4,
1330 D3DPSREGISTER_Color_Specular = 5,
1331 D3DPSREGISTER_Color_Glow = 6,
1332 D3DPSREGISTER_Color_Pants = 7,
1333 D3DPSREGISTER_Color_Shirt = 8,
1334 D3DPSREGISTER_DeferredColor_Ambient = 9,
1335 D3DPSREGISTER_DeferredColor_Diffuse = 10,
1336 D3DPSREGISTER_DeferredColor_Specular = 11,
1337 D3DPSREGISTER_DeferredMod_Diffuse = 12,
1338 D3DPSREGISTER_DeferredMod_Specular = 13,
1339 D3DPSREGISTER_DistortScaleRefractReflect = 14,
1340 D3DPSREGISTER_EyePosition = 15, // unused
1341 D3DPSREGISTER_FogColor = 16,
1342 D3DPSREGISTER_FogHeightFade = 17,
1343 D3DPSREGISTER_FogPlane = 18,
1344 D3DPSREGISTER_FogPlaneViewDist = 19,
1345 D3DPSREGISTER_FogRangeRecip = 20,
1346 D3DPSREGISTER_LightColor = 21,
1347 D3DPSREGISTER_LightDir = 22, // unused
1348 D3DPSREGISTER_LightPosition = 23,
1349 D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1350 D3DPSREGISTER_PixelSize = 25,
1351 D3DPSREGISTER_ReflectColor = 26,
1352 D3DPSREGISTER_ReflectFactor = 27,
1353 D3DPSREGISTER_ReflectOffset = 28,
1354 D3DPSREGISTER_RefractColor = 29,
1355 D3DPSREGISTER_Saturation = 30,
1356 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1357 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1358 D3DPSREGISTER_ScreenToDepth = 33,
1359 D3DPSREGISTER_ShadowMap_Parameters = 34,
1360 D3DPSREGISTER_ShadowMap_TextureScale = 35,
1361 D3DPSREGISTER_SpecularPower = 36,
1362 D3DPSREGISTER_UserVec1 = 37,
1363 D3DPSREGISTER_UserVec2 = 38,
1364 D3DPSREGISTER_UserVec3 = 39,
1365 D3DPSREGISTER_UserVec4 = 40,
1366 D3DPSREGISTER_ViewTintColor = 41,
1367 D3DPSREGISTER_PixelToScreenTexCoord = 42,
1368 D3DPSREGISTER_BloomColorSubtract = 43,
1369 D3DPSREGISTER_ViewToLight = 44, // float4x4
1370 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1371 D3DPSREGISTER_NormalmapScrollBlend = 52,
1376 /// information about each possible shader permutation
1377 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1378 /// currently selected permutation
1379 r_hlsl_permutation_t *r_hlsl_permutation;
1380 /// storage for permutations linked in the hash table
1381 memexpandablearray_t r_hlsl_permutationarray;
1383 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1385 //unsigned int hashdepth = 0;
1386 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1387 r_hlsl_permutation_t *p;
1388 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1390 if (p->mode == mode && p->permutation == permutation)
1392 //if (hashdepth > 10)
1393 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1398 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1400 p->permutation = permutation;
1401 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1402 r_hlsl_permutationhash[mode][hashindex] = p;
1403 //if (hashdepth > 10)
1404 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1408 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1411 if (!filename || !filename[0])
1413 if (!strcmp(filename, "hlsl/default.hlsl"))
1415 if (!hlslshaderstring)
1417 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1418 if (hlslshaderstring)
1419 Con_DPrintf("Loading shaders from file %s...\n", filename);
1421 hlslshaderstring = (char *)builtinhlslshaderstring;
1423 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1424 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1425 return shaderstring;
1427 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1430 if (printfromdisknotice)
1431 Con_DPrintf("from disk %s... ", filename);
1432 return shaderstring;
1434 return shaderstring;
1438 //#include <d3dx9shader.h>
1439 //#include <d3dx9mesh.h>
1441 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1443 DWORD *vsbin = NULL;
1444 DWORD *psbin = NULL;
1445 fs_offset_t vsbinsize;
1446 fs_offset_t psbinsize;
1447 // IDirect3DVertexShader9 *vs = NULL;
1448 // IDirect3DPixelShader9 *ps = NULL;
1449 ID3DXBuffer *vslog = NULL;
1450 ID3DXBuffer *vsbuffer = NULL;
1451 ID3DXConstantTable *vsconstanttable = NULL;
1452 ID3DXBuffer *pslog = NULL;
1453 ID3DXBuffer *psbuffer = NULL;
1454 ID3DXConstantTable *psconstanttable = NULL;
1457 char temp[MAX_INPUTLINE];
1458 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1459 qboolean debugshader = gl_paranoid.integer != 0;
1460 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1461 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1464 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1465 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1467 if ((!vsbin && vertstring) || (!psbin && fragstring))
1469 const char* dllnames_d3dx9 [] =
1493 dllhandle_t d3dx9_dll = NULL;
1494 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1495 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1496 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1497 dllfunction_t d3dx9_dllfuncs[] =
1499 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
1500 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
1501 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
1504 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1506 DWORD shaderflags = 0;
1508 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1509 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1510 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1511 if (vertstring && vertstring[0])
1515 // vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1516 // FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1517 FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1518 vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1521 vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1524 vsbinsize = vsbuffer->GetBufferSize();
1525 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1526 memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1527 vsbuffer->Release();
1531 strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1532 Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1536 if (fragstring && fragstring[0])
1540 // psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1541 // FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1542 FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1543 psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1546 psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1549 psbinsize = psbuffer->GetBufferSize();
1550 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1551 memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1552 psbuffer->Release();
1556 strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1557 Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1561 Sys_UnloadLibrary(&d3dx9_dll);
1564 Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1568 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1569 if (FAILED(vsresult))
1570 Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1571 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1572 if (FAILED(psresult))
1573 Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1575 // free the shader data
1576 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1577 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1580 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1583 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1584 int vertstring_length = 0;
1585 int geomstring_length = 0;
1586 int fragstring_length = 0;
1588 char *vertexstring, *geometrystring, *fragmentstring;
1589 char *vertstring, *geomstring, *fragstring;
1590 char permutationname[256];
1591 char cachename[256];
1592 int vertstrings_count = 0;
1593 int geomstrings_count = 0;
1594 int fragstrings_count = 0;
1595 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1596 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1597 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1602 p->vertexshader = NULL;
1603 p->pixelshader = NULL;
1605 permutationname[0] = 0;
1607 vertexstring = R_HLSL_GetText(modeinfo->vertexfilename, true);
1608 geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1609 fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1611 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1612 strlcat(cachename, "hlsl/", sizeof(cachename));
1614 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1615 vertstrings_count = 0;
1616 geomstrings_count = 0;
1617 fragstrings_count = 0;
1618 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1619 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1620 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1622 // the first pretext is which type of shader to compile as
1623 // (later these will all be bound together as a program object)
1624 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1625 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1626 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1628 // the second pretext is the mode (for example a light source)
1629 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1630 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1631 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1632 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1633 strlcat(cachename, modeinfo->name, sizeof(cachename));
1635 // now add all the permutation pretexts
1636 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1638 if (permutation & (1<<i))
1640 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1641 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1642 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1643 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1644 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1648 // keep line numbers correct
1649 vertstrings_list[vertstrings_count++] = "\n";
1650 geomstrings_list[geomstrings_count++] = "\n";
1651 fragstrings_list[fragstrings_count++] = "\n";
1656 R_CompileShader_AddStaticParms(mode, permutation);
1657 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1658 vertstrings_count += shaderstaticparms_count;
1659 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1660 geomstrings_count += shaderstaticparms_count;
1661 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1662 fragstrings_count += shaderstaticparms_count;
1664 // replace spaces in the cachename with _ characters
1665 for (i = 0;cachename[i];i++)
1666 if (cachename[i] == ' ')
1669 // now append the shader text itself
1670 vertstrings_list[vertstrings_count++] = vertexstring;
1671 geomstrings_list[geomstrings_count++] = geometrystring;
1672 fragstrings_list[fragstrings_count++] = fragmentstring;
1674 // if any sources were NULL, clear the respective list
1676 vertstrings_count = 0;
1677 if (!geometrystring)
1678 geomstrings_count = 0;
1679 if (!fragmentstring)
1680 fragstrings_count = 0;
1682 vertstring_length = 0;
1683 for (i = 0;i < vertstrings_count;i++)
1684 vertstring_length += strlen(vertstrings_list[i]);
1685 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1686 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1687 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1689 geomstring_length = 0;
1690 for (i = 0;i < geomstrings_count;i++)
1691 geomstring_length += strlen(geomstrings_list[i]);
1692 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1693 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1694 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1696 fragstring_length = 0;
1697 for (i = 0;i < fragstrings_count;i++)
1698 fragstring_length += strlen(fragstrings_list[i]);
1699 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1700 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1701 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1703 // try to load the cached shader, or generate one
1704 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1706 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1707 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1709 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
1713 Mem_Free(vertstring);
1715 Mem_Free(geomstring);
1717 Mem_Free(fragstring);
1719 Mem_Free(vertexstring);
1721 Mem_Free(geometrystring);
1723 Mem_Free(fragmentstring);
1726 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1727 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1728 static inline void hlslVSSetParameter4f(D3DVSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1729 static inline void hlslVSSetParameter3f(D3DVSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1730 static inline void hlslVSSetParameter2f(D3DVSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1731 static inline void hlslVSSetParameter1f(D3DVSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1733 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1734 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1735 static inline void hlslPSSetParameter4f(D3DPSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1736 static inline void hlslPSSetParameter3f(D3DPSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1737 static inline void hlslPSSetParameter2f(D3DPSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1738 static inline void hlslPSSetParameter1f(D3DPSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1740 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1742 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1743 if (r_hlsl_permutation != perm)
1745 r_hlsl_permutation = perm;
1746 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1748 if (!r_hlsl_permutation->compiled)
1749 R_HLSL_CompilePermutation(perm, mode, permutation);
1750 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1752 // remove features until we find a valid permutation
1754 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1756 // reduce i more quickly whenever it would not remove any bits
1757 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1758 if (!(permutation & j))
1761 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1762 if (!r_hlsl_permutation->compiled)
1763 R_HLSL_CompilePermutation(perm, mode, permutation);
1764 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1767 if (i >= SHADERPERMUTATION_COUNT)
1769 //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1770 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1771 return; // no bit left to clear, entire mode is broken
1775 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1776 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1778 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1779 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1780 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1784 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1786 DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1787 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1788 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1789 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1792 void R_GLSL_Restart_f(void)
1794 unsigned int i, limit;
1795 if (glslshaderstring && glslshaderstring != builtinshaderstring)
1796 Mem_Free(glslshaderstring);
1797 glslshaderstring = NULL;
1798 if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1799 Mem_Free(hlslshaderstring);
1800 hlslshaderstring = NULL;
1801 switch(vid.renderpath)
1803 case RENDERPATH_D3D9:
1806 r_hlsl_permutation_t *p;
1807 r_hlsl_permutation = NULL;
1808 limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1809 for (i = 0;i < limit;i++)
1811 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1813 if (p->vertexshader)
1814 IDirect3DVertexShader9_Release(p->vertexshader);
1816 IDirect3DPixelShader9_Release(p->pixelshader);
1817 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1820 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1824 case RENDERPATH_D3D10:
1825 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1827 case RENDERPATH_D3D11:
1828 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1830 case RENDERPATH_GL20:
1831 case RENDERPATH_GLES2:
1833 r_glsl_permutation_t *p;
1834 r_glsl_permutation = NULL;
1835 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1836 for (i = 0;i < limit;i++)
1838 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1840 GL_Backend_FreeProgram(p->program);
1841 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1844 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1847 case RENDERPATH_GL11:
1848 case RENDERPATH_GL13:
1849 case RENDERPATH_GLES1:
1851 case RENDERPATH_SOFT:
1856 void R_GLSL_DumpShader_f(void)
1861 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1864 FS_Print(file, "/* The engine may define the following macros:\n");
1865 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1866 for (i = 0;i < SHADERMODE_COUNT;i++)
1867 FS_Print(file, glslshadermodeinfo[i].pretext);
1868 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1869 FS_Print(file, shaderpermutationinfo[i].pretext);
1870 FS_Print(file, "*/\n");
1871 FS_Print(file, builtinshaderstring);
1873 Con_Printf("glsl/default.glsl written\n");
1876 Con_Printf("failed to write to glsl/default.glsl\n");
1878 file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1881 FS_Print(file, "/* The engine may define the following macros:\n");
1882 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1883 for (i = 0;i < SHADERMODE_COUNT;i++)
1884 FS_Print(file, hlslshadermodeinfo[i].pretext);
1885 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1886 FS_Print(file, shaderpermutationinfo[i].pretext);
1887 FS_Print(file, "*/\n");
1888 FS_Print(file, builtinhlslshaderstring);
1890 Con_Printf("hlsl/default.hlsl written\n");
1893 Con_Printf("failed to write to hlsl/default.hlsl\n");
1896 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean notrippy)
1898 unsigned int permutation = 0;
1899 if (r_trippy.integer && !notrippy)
1900 permutation |= SHADERPERMUTATION_TRIPPY;
1901 permutation |= SHADERPERMUTATION_VIEWTINT;
1903 permutation |= SHADERPERMUTATION_DIFFUSE;
1905 permutation |= SHADERPERMUTATION_SPECULAR;
1906 if (texturemode == GL_MODULATE)
1907 permutation |= SHADERPERMUTATION_COLORMAPPING;
1908 else if (texturemode == GL_ADD)
1909 permutation |= SHADERPERMUTATION_GLOW;
1910 else if (texturemode == GL_DECAL)
1911 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1913 texturemode = GL_MODULATE;
1914 if (vid.allowalphatocoverage)
1915 GL_AlphaToCoverage(false);
1916 switch (vid.renderpath)
1918 case RENDERPATH_D3D9:
1920 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1921 R_Mesh_TexBind(GL20TU_FIRST , first );
1922 R_Mesh_TexBind(GL20TU_SECOND, second);
1925 case RENDERPATH_D3D10:
1926 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1928 case RENDERPATH_D3D11:
1929 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1931 case RENDERPATH_GL20:
1932 case RENDERPATH_GLES2:
1933 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
1934 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1935 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1937 case RENDERPATH_GL13:
1938 case RENDERPATH_GLES1:
1939 R_Mesh_TexBind(0, first );
1940 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1941 R_Mesh_TexBind(1, second);
1943 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1945 case RENDERPATH_GL11:
1946 R_Mesh_TexBind(0, first );
1948 case RENDERPATH_SOFT:
1949 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
1950 R_Mesh_TexBind(GL20TU_FIRST , first );
1951 R_Mesh_TexBind(GL20TU_SECOND, second);
1956 void R_SetupShader_DepthOrShadow(qboolean notrippy)
1958 unsigned int permutation = 0;
1959 if (r_trippy.integer && !notrippy)
1960 permutation |= SHADERPERMUTATION_TRIPPY;
1961 if (vid.allowalphatocoverage)
1962 GL_AlphaToCoverage(false);
1963 switch (vid.renderpath)
1965 case RENDERPATH_D3D9:
1967 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1970 case RENDERPATH_D3D10:
1971 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1973 case RENDERPATH_D3D11:
1974 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1976 case RENDERPATH_GL20:
1977 case RENDERPATH_GLES2:
1978 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1980 case RENDERPATH_GL13:
1981 case RENDERPATH_GLES1:
1982 R_Mesh_TexBind(0, 0);
1983 R_Mesh_TexBind(1, 0);
1985 case RENDERPATH_GL11:
1986 R_Mesh_TexBind(0, 0);
1988 case RENDERPATH_SOFT:
1989 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1994 void R_SetupShader_ShowDepth(qboolean notrippy)
1996 int permutation = 0;
1997 if (r_trippy.integer && !notrippy)
1998 permutation |= SHADERPERMUTATION_TRIPPY;
1999 if (r_trippy.integer)
2000 permutation |= SHADERPERMUTATION_TRIPPY;
2001 if (vid.allowalphatocoverage)
2002 GL_AlphaToCoverage(false);
2003 switch (vid.renderpath)
2005 case RENDERPATH_D3D9:
2007 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, permutation);
2010 case RENDERPATH_D3D10:
2011 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2013 case RENDERPATH_D3D11:
2014 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2016 case RENDERPATH_GL20:
2017 case RENDERPATH_GLES2:
2018 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, permutation);
2020 case RENDERPATH_GL13:
2021 case RENDERPATH_GLES1:
2023 case RENDERPATH_GL11:
2025 case RENDERPATH_SOFT:
2026 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, permutation);
2031 extern qboolean r_shadow_usingdeferredprepass;
2032 extern cvar_t r_shadow_deferred_8bitrange;
2033 extern rtexture_t *r_shadow_attenuationgradienttexture;
2034 extern rtexture_t *r_shadow_attenuation2dtexture;
2035 extern rtexture_t *r_shadow_attenuation3dtexture;
2036 extern qboolean r_shadow_usingshadowmap2d;
2037 extern qboolean r_shadow_usingshadowmaportho;
2038 extern float r_shadow_shadowmap_texturescale[2];
2039 extern float r_shadow_shadowmap_parameters[4];
2040 extern qboolean r_shadow_shadowmapvsdct;
2041 extern qboolean r_shadow_shadowmapsampler;
2042 extern int r_shadow_shadowmappcf;
2043 extern rtexture_t *r_shadow_shadowmap2dtexture;
2044 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2045 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2046 extern matrix4x4_t r_shadow_shadowmapmatrix;
2047 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2048 extern int r_shadow_prepass_width;
2049 extern int r_shadow_prepass_height;
2050 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2051 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2052 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2053 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2054 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2056 #define BLENDFUNC_ALLOWS_COLORMOD 1
2057 #define BLENDFUNC_ALLOWS_FOG 2
2058 #define BLENDFUNC_ALLOWS_FOG_HACK0 4
2059 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2060 #define BLENDFUNC_ALLOWS_ANYFOG (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2061 static int R_BlendFuncFlags(int src, int dst)
2065 // a blendfunc allows colormod if:
2066 // a) it can never keep the destination pixel invariant, or
2067 // b) it can keep the destination pixel invariant, and still can do so if colormodded
2068 // this is to prevent unintended side effects from colormod
2070 // a blendfunc allows fog if:
2071 // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2072 // this is to prevent unintended side effects from fog
2074 // these checks are the output of fogeval.pl
2076 r |= BLENDFUNC_ALLOWS_COLORMOD;
2077 if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2078 if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2079 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2080 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2081 if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2082 if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2083 if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2084 if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2085 if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2086 if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2087 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2088 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2089 if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2090 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2091 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2092 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2093 if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2094 if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2095 if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2096 if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2097 if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2102 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)
2104 // select a permutation of the lighting shader appropriate to this
2105 // combination of texture, entity, light source, and fogging, only use the
2106 // minimum features necessary to avoid wasting rendering time in the
2107 // fragment shader on features that are not being used
2108 unsigned int permutation = 0;
2109 unsigned int mode = 0;
2111 static float dummy_colormod[3] = {1, 1, 1};
2112 float *colormod = rsurface.colormod;
2114 matrix4x4_t tempmatrix;
2115 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2116 if (r_trippy.integer && !notrippy)
2117 permutation |= SHADERPERMUTATION_TRIPPY;
2118 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2119 permutation |= SHADERPERMUTATION_ALPHAKILL;
2120 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2121 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2122 if (rsurfacepass == RSURFPASS_BACKGROUND)
2124 // distorted background
2125 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2127 mode = SHADERMODE_WATER;
2128 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2130 // this is the right thing to do for wateralpha
2131 GL_BlendFunc(GL_ONE, GL_ZERO);
2132 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2136 // this is the right thing to do for entity alpha
2137 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2138 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2141 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2143 mode = SHADERMODE_REFRACTION;
2144 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2145 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2149 mode = SHADERMODE_GENERIC;
2150 permutation |= SHADERPERMUTATION_DIFFUSE;
2151 GL_BlendFunc(GL_ONE, GL_ZERO);
2152 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2154 if (vid.allowalphatocoverage)
2155 GL_AlphaToCoverage(false);
2157 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2159 if (r_glsl_offsetmapping.integer)
2161 switch(rsurface.texture->offsetmapping)
2163 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2164 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2165 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2166 case OFFSETMAPPING_OFF: break;
2169 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2170 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2171 // normalmap (deferred prepass), may use alpha test on diffuse
2172 mode = SHADERMODE_DEFERREDGEOMETRY;
2173 GL_BlendFunc(GL_ONE, GL_ZERO);
2174 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2175 if (vid.allowalphatocoverage)
2176 GL_AlphaToCoverage(false);
2178 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2180 if (r_glsl_offsetmapping.integer)
2182 switch(rsurface.texture->offsetmapping)
2184 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2185 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2186 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2187 case OFFSETMAPPING_OFF: break;
2190 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2191 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2193 mode = SHADERMODE_LIGHTSOURCE;
2194 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2195 permutation |= SHADERPERMUTATION_CUBEFILTER;
2196 if (diffusescale > 0)
2197 permutation |= SHADERPERMUTATION_DIFFUSE;
2198 if (specularscale > 0)
2199 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2200 if (r_refdef.fogenabled)
2201 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2202 if (rsurface.texture->colormapping)
2203 permutation |= SHADERPERMUTATION_COLORMAPPING;
2204 if (r_shadow_usingshadowmap2d)
2206 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2207 if(r_shadow_shadowmapvsdct)
2208 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2210 if (r_shadow_shadowmapsampler)
2211 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2212 if (r_shadow_shadowmappcf > 1)
2213 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2214 else if (r_shadow_shadowmappcf)
2215 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2217 if (rsurface.texture->reflectmasktexture)
2218 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2219 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2220 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2221 if (vid.allowalphatocoverage)
2222 GL_AlphaToCoverage(false);
2224 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2226 if (r_glsl_offsetmapping.integer)
2228 switch(rsurface.texture->offsetmapping)
2230 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2231 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2232 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2233 case OFFSETMAPPING_OFF: break;
2236 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2237 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2238 // unshaded geometry (fullbright or ambient model lighting)
2239 mode = SHADERMODE_FLATCOLOR;
2240 ambientscale = diffusescale = specularscale = 0;
2241 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2242 permutation |= SHADERPERMUTATION_GLOW;
2243 if (r_refdef.fogenabled)
2244 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2245 if (rsurface.texture->colormapping)
2246 permutation |= SHADERPERMUTATION_COLORMAPPING;
2247 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2249 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2250 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2252 if (r_shadow_shadowmapsampler)
2253 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2254 if (r_shadow_shadowmappcf > 1)
2255 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2256 else if (r_shadow_shadowmappcf)
2257 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2259 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2260 permutation |= SHADERPERMUTATION_REFLECTION;
2261 if (rsurface.texture->reflectmasktexture)
2262 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2263 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2264 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2265 // when using alphatocoverage, we don't need alphakill
2266 if (vid.allowalphatocoverage)
2268 if (r_transparent_alphatocoverage.integer)
2270 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2271 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2274 GL_AlphaToCoverage(false);
2277 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2279 if (r_glsl_offsetmapping.integer)
2281 switch(rsurface.texture->offsetmapping)
2283 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2284 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2285 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2286 case OFFSETMAPPING_OFF: break;
2289 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2290 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2291 // directional model lighting
2292 mode = SHADERMODE_LIGHTDIRECTION;
2293 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2294 permutation |= SHADERPERMUTATION_GLOW;
2295 permutation |= SHADERPERMUTATION_DIFFUSE;
2296 if (specularscale > 0)
2297 permutation |= SHADERPERMUTATION_SPECULAR;
2298 if (r_refdef.fogenabled)
2299 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2300 if (rsurface.texture->colormapping)
2301 permutation |= SHADERPERMUTATION_COLORMAPPING;
2302 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2304 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2305 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2307 if (r_shadow_shadowmapsampler)
2308 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2309 if (r_shadow_shadowmappcf > 1)
2310 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2311 else if (r_shadow_shadowmappcf)
2312 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2314 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2315 permutation |= SHADERPERMUTATION_REFLECTION;
2316 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2317 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2318 if (rsurface.texture->reflectmasktexture)
2319 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2320 if (r_shadow_bouncegridtexture)
2322 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2323 if (r_shadow_bouncegriddirectional)
2324 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2326 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2327 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2328 // when using alphatocoverage, we don't need alphakill
2329 if (vid.allowalphatocoverage)
2331 if (r_transparent_alphatocoverage.integer)
2333 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2334 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2337 GL_AlphaToCoverage(false);
2340 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2342 if (r_glsl_offsetmapping.integer)
2344 switch(rsurface.texture->offsetmapping)
2346 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2347 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2348 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2349 case OFFSETMAPPING_OFF: break;
2352 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2353 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2354 // ambient model lighting
2355 mode = SHADERMODE_LIGHTDIRECTION;
2356 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2357 permutation |= SHADERPERMUTATION_GLOW;
2358 if (r_refdef.fogenabled)
2359 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2360 if (rsurface.texture->colormapping)
2361 permutation |= SHADERPERMUTATION_COLORMAPPING;
2362 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2364 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2365 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2367 if (r_shadow_shadowmapsampler)
2368 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2369 if (r_shadow_shadowmappcf > 1)
2370 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2371 else if (r_shadow_shadowmappcf)
2372 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2374 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2375 permutation |= SHADERPERMUTATION_REFLECTION;
2376 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2377 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2378 if (rsurface.texture->reflectmasktexture)
2379 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2380 if (r_shadow_bouncegridtexture)
2382 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2383 if (r_shadow_bouncegriddirectional)
2384 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2386 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2387 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2388 // when using alphatocoverage, we don't need alphakill
2389 if (vid.allowalphatocoverage)
2391 if (r_transparent_alphatocoverage.integer)
2393 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2394 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2397 GL_AlphaToCoverage(false);
2402 if (r_glsl_offsetmapping.integer)
2404 switch(rsurface.texture->offsetmapping)
2406 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2407 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2408 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2409 case OFFSETMAPPING_OFF: break;
2412 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2413 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2415 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2416 permutation |= SHADERPERMUTATION_GLOW;
2417 if (r_refdef.fogenabled)
2418 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2419 if (rsurface.texture->colormapping)
2420 permutation |= SHADERPERMUTATION_COLORMAPPING;
2421 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2423 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2424 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2426 if (r_shadow_shadowmapsampler)
2427 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2428 if (r_shadow_shadowmappcf > 1)
2429 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2430 else if (r_shadow_shadowmappcf)
2431 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2433 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2434 permutation |= SHADERPERMUTATION_REFLECTION;
2435 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2436 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2437 if (rsurface.texture->reflectmasktexture)
2438 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2439 if (FAKELIGHT_ENABLED)
2441 // fake lightmapping (q1bsp, q3bsp, fullbright map)
2442 mode = SHADERMODE_FAKELIGHT;
2443 permutation |= SHADERPERMUTATION_DIFFUSE;
2444 if (specularscale > 0)
2445 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2447 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2449 // deluxemapping (light direction texture)
2450 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2451 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2453 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2454 permutation |= SHADERPERMUTATION_DIFFUSE;
2455 if (specularscale > 0)
2456 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2458 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2460 // fake deluxemapping (uniform light direction in tangentspace)
2461 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2462 permutation |= SHADERPERMUTATION_DIFFUSE;
2463 if (specularscale > 0)
2464 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2466 else if (rsurface.uselightmaptexture)
2468 // ordinary lightmapping (q1bsp, q3bsp)
2469 mode = SHADERMODE_LIGHTMAP;
2473 // ordinary vertex coloring (q3bsp)
2474 mode = SHADERMODE_VERTEXCOLOR;
2476 if (r_shadow_bouncegridtexture)
2478 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2479 if (r_shadow_bouncegriddirectional)
2480 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2482 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2483 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2484 // when using alphatocoverage, we don't need alphakill
2485 if (vid.allowalphatocoverage)
2487 if (r_transparent_alphatocoverage.integer)
2489 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2490 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2493 GL_AlphaToCoverage(false);
2496 if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2497 colormod = dummy_colormod;
2498 if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2499 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2500 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2501 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2502 switch(vid.renderpath)
2504 case RENDERPATH_D3D9:
2506 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);
2507 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2508 R_SetupShader_SetPermutationHLSL(mode, permutation);
2509 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2510 if (mode == SHADERMODE_LIGHTSOURCE)
2512 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2513 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2517 if (mode == SHADERMODE_LIGHTDIRECTION)
2519 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2522 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2523 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2524 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2525 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2526 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2528 if (mode == SHADERMODE_LIGHTSOURCE)
2530 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2531 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2532 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2533 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2534 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2536 // additive passes are only darkened by fog, not tinted
2537 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2538 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2542 if (mode == SHADERMODE_FLATCOLOR)
2544 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2546 else if (mode == SHADERMODE_LIGHTDIRECTION)
2548 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]);
2549 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2550 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);
2551 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);
2552 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2553 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2554 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2558 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2559 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2560 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);
2561 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);
2562 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2564 // additive passes are only darkened by fog, not tinted
2565 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2566 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2568 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2569 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);
2570 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2571 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2572 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2573 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2574 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2575 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2576 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2577 if (mode == SHADERMODE_WATER)
2578 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2580 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2581 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2582 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2583 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));
2584 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2585 if (rsurface.texture->pantstexture)
2586 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2588 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2589 if (rsurface.texture->shirttexture)
2590 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2592 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2593 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2594 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2595 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2596 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2597 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2598 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2599 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2600 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2601 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2603 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2604 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2606 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2607 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2608 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2609 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2610 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2611 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2612 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2613 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2614 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2615 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2616 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2617 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2618 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2619 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2620 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2621 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2622 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2623 if (rsurfacepass == RSURFPASS_BACKGROUND)
2625 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2626 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2627 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2631 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2633 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2634 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2635 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2636 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2637 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2639 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2640 if (rsurface.rtlight)
2642 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2643 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2648 case RENDERPATH_D3D10:
2649 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2651 case RENDERPATH_D3D11:
2652 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2654 case RENDERPATH_GL20:
2655 case RENDERPATH_GLES2:
2656 if (!vid.useinterleavedarrays)
2658 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);
2659 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2660 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2661 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2662 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2663 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2664 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2665 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2669 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);
2670 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2672 R_SetupShader_SetPermutationGLSL(mode, permutation);
2673 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2674 if (mode == SHADERMODE_LIGHTSOURCE)
2676 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2677 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2678 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2679 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2680 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2681 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);
2683 // additive passes are only darkened by fog, not tinted
2684 if (r_glsl_permutation->loc_FogColor >= 0)
2685 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2686 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2690 if (mode == SHADERMODE_FLATCOLOR)
2692 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2694 else if (mode == SHADERMODE_LIGHTDIRECTION)
2696 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]);
2697 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]);
2698 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);
2699 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);
2700 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);
2701 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]);
2702 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]);
2706 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]);
2707 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]);
2708 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);
2709 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);
2710 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);
2712 // additive passes are only darkened by fog, not tinted
2713 if (r_glsl_permutation->loc_FogColor >= 0)
2715 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2716 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2718 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2720 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);
2721 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]);
2722 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]);
2723 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]);
2724 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]);
2725 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2726 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2727 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2728 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]);
2730 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2731 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2732 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2733 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]);
2734 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]);
2736 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2737 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));
2738 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2739 if (r_glsl_permutation->loc_Color_Pants >= 0)
2741 if (rsurface.texture->pantstexture)
2742 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2744 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2746 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2748 if (rsurface.texture->shirttexture)
2749 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2751 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2753 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]);
2754 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2755 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2756 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2757 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2758 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2759 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2760 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2761 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2763 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]);
2764 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2765 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);}
2766 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2768 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
2769 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
2770 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
2771 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
2772 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
2773 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
2774 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
2775 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
2776 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
2777 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
2778 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
2779 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
2780 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
2781 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
2782 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);
2783 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
2784 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
2785 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2786 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2787 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2788 if (rsurfacepass == RSURFPASS_BACKGROUND)
2790 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);
2791 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);
2792 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);
2796 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);
2798 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2799 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2800 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
2801 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
2802 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2804 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture );
2805 if (rsurface.rtlight)
2807 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2808 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2811 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2814 case RENDERPATH_GL11:
2815 case RENDERPATH_GL13:
2816 case RENDERPATH_GLES1:
2818 case RENDERPATH_SOFT:
2819 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);
2820 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2821 R_SetupShader_SetPermutationSoft(mode, permutation);
2822 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2823 if (mode == SHADERMODE_LIGHTSOURCE)
2825 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2826 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2827 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2828 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2829 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2830 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2832 // additive passes are only darkened by fog, not tinted
2833 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2834 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2838 if (mode == SHADERMODE_FLATCOLOR)
2840 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2842 else if (mode == SHADERMODE_LIGHTDIRECTION)
2844 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]);
2845 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2846 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);
2847 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);
2848 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2849 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]);
2850 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2854 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2855 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2856 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);
2857 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);
2858 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2860 // additive passes are only darkened by fog, not tinted
2861 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2862 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2864 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2865 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);
2866 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2867 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2868 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]);
2869 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]);
2870 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2871 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2872 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2873 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2875 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2876 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2877 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2878 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2879 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]);
2881 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2882 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));
2883 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2884 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2886 if (rsurface.texture->pantstexture)
2887 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2889 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2891 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2893 if (rsurface.texture->shirttexture)
2894 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2896 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2898 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2899 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2900 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2901 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2902 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2903 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2904 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2905 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2906 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2908 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2909 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2911 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2912 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2913 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2914 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2915 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2916 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2917 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2918 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2919 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2920 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2921 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2922 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2923 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2924 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2925 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2926 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2927 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2928 if (rsurfacepass == RSURFPASS_BACKGROUND)
2930 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2931 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2932 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2936 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2938 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2939 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2940 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2941 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2942 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2944 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2945 if (rsurface.rtlight)
2947 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2948 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2955 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2957 // select a permutation of the lighting shader appropriate to this
2958 // combination of texture, entity, light source, and fogging, only use the
2959 // minimum features necessary to avoid wasting rendering time in the
2960 // fragment shader on features that are not being used
2961 unsigned int permutation = 0;
2962 unsigned int mode = 0;
2963 const float *lightcolorbase = rtlight->currentcolor;
2964 float ambientscale = rtlight->ambientscale;
2965 float diffusescale = rtlight->diffusescale;
2966 float specularscale = rtlight->specularscale;
2967 // this is the location of the light in view space
2968 vec3_t viewlightorigin;
2969 // this transforms from view space (camera) to light space (cubemap)
2970 matrix4x4_t viewtolight;
2971 matrix4x4_t lighttoview;
2972 float viewtolight16f[16];
2973 float range = 1.0f / r_shadow_deferred_8bitrange.value;
2975 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2976 if (rtlight->currentcubemap != r_texture_whitecube)
2977 permutation |= SHADERPERMUTATION_CUBEFILTER;
2978 if (diffusescale > 0)
2979 permutation |= SHADERPERMUTATION_DIFFUSE;
2980 if (specularscale > 0 && r_shadow_gloss.integer > 0)
2981 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2982 if (r_shadow_usingshadowmap2d)
2984 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2985 if (r_shadow_shadowmapvsdct)
2986 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2988 if (r_shadow_shadowmapsampler)
2989 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2990 if (r_shadow_shadowmappcf > 1)
2991 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2992 else if (r_shadow_shadowmappcf)
2993 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2995 if (vid.allowalphatocoverage)
2996 GL_AlphaToCoverage(false);
2997 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2998 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2999 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3000 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3001 switch(vid.renderpath)
3003 case RENDERPATH_D3D9:
3005 R_SetupShader_SetPermutationHLSL(mode, permutation);
3006 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3007 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3008 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
3009 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
3010 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3011 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3012 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3013 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
3014 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3015 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3017 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3018 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthcolortexture );
3019 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3020 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3021 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dcolortexture );
3022 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3025 case RENDERPATH_D3D10:
3026 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3028 case RENDERPATH_D3D11:
3029 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3031 case RENDERPATH_GL20:
3032 case RENDERPATH_GLES2:
3033 R_SetupShader_SetPermutationGLSL(mode, permutation);
3034 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3035 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
3036 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);
3037 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);
3038 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);
3039 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]);
3040 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]);
3041 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));
3042 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]);
3043 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
3045 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
3046 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
3047 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
3048 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
3049 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );
3050 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
3052 case RENDERPATH_GL11:
3053 case RENDERPATH_GL13:
3054 case RENDERPATH_GLES1:
3056 case RENDERPATH_SOFT:
3057 R_SetupShader_SetPermutationGLSL(mode, permutation);
3058 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3059 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
3060 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
3061 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
3062 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3063 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3064 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]);
3065 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));
3066 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3067 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3069 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3070 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
3071 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3072 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3073 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
3074 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3079 #define SKINFRAME_HASH 1024
3083 int loadsequence; // incremented each level change
3084 memexpandablearray_t array;
3085 skinframe_t *hash[SKINFRAME_HASH];
3088 r_skinframe_t r_skinframe;
3090 void R_SkinFrame_PrepareForPurge(void)
3092 r_skinframe.loadsequence++;
3093 // wrap it without hitting zero
3094 if (r_skinframe.loadsequence >= 200)
3095 r_skinframe.loadsequence = 1;
3098 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3102 // mark the skinframe as used for the purging code
3103 skinframe->loadsequence = r_skinframe.loadsequence;
3106 void R_SkinFrame_Purge(void)
3110 for (i = 0;i < SKINFRAME_HASH;i++)
3112 for (s = r_skinframe.hash[i];s;s = s->next)
3114 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3116 if (s->merged == s->base)
3118 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3119 R_PurgeTexture(s->stain );s->stain = NULL;
3120 R_PurgeTexture(s->merged);s->merged = NULL;
3121 R_PurgeTexture(s->base );s->base = NULL;
3122 R_PurgeTexture(s->pants );s->pants = NULL;
3123 R_PurgeTexture(s->shirt );s->shirt = NULL;
3124 R_PurgeTexture(s->nmap );s->nmap = NULL;
3125 R_PurgeTexture(s->gloss );s->gloss = NULL;
3126 R_PurgeTexture(s->glow );s->glow = NULL;
3127 R_PurgeTexture(s->fog );s->fog = NULL;
3128 R_PurgeTexture(s->reflect);s->reflect = NULL;
3129 s->loadsequence = 0;
3135 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3137 char basename[MAX_QPATH];
3139 Image_StripImageExtension(name, basename, sizeof(basename));
3141 if( last == NULL ) {
3143 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3144 item = r_skinframe.hash[hashindex];
3149 // linearly search through the hash bucket
3150 for( ; item ; item = item->next ) {
3151 if( !strcmp( item->basename, basename ) ) {
3158 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3162 char basename[MAX_QPATH];
3164 Image_StripImageExtension(name, basename, sizeof(basename));
3166 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3167 for (item = r_skinframe.hash[hashindex];item;item = item->next)
3168 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3172 rtexture_t *dyntexture;
3173 // check whether its a dynamic texture
3174 dyntexture = CL_GetDynTexture( basename );
3175 if (!add && !dyntexture)
3177 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3178 memset(item, 0, sizeof(*item));
3179 strlcpy(item->basename, basename, sizeof(item->basename));
3180 item->base = dyntexture; // either NULL or dyntexture handle
3181 item->textureflags = textureflags;
3182 item->comparewidth = comparewidth;
3183 item->compareheight = compareheight;
3184 item->comparecrc = comparecrc;
3185 item->next = r_skinframe.hash[hashindex];
3186 r_skinframe.hash[hashindex] = item;
3188 else if( item->base == NULL )
3190 rtexture_t *dyntexture;
3191 // check whether its a dynamic texture
3192 // 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]
3193 dyntexture = CL_GetDynTexture( basename );
3194 item->base = dyntexture; // either NULL or dyntexture handle
3197 R_SkinFrame_MarkUsed(item);
3201 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3203 unsigned long long avgcolor[5], wsum; \
3211 for(pix = 0; pix < cnt; ++pix) \
3214 for(comp = 0; comp < 3; ++comp) \
3216 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3219 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3221 for(comp = 0; comp < 3; ++comp) \
3222 avgcolor[comp] += getpixel * w; \
3225 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3226 avgcolor[4] += getpixel; \
3228 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3230 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3231 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3232 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3233 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3236 extern cvar_t gl_picmip;
3237 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3240 unsigned char *pixels;
3241 unsigned char *bumppixels;
3242 unsigned char *basepixels = NULL;
3243 int basepixels_width = 0;
3244 int basepixels_height = 0;
3245 skinframe_t *skinframe;
3246 rtexture_t *ddsbase = NULL;
3247 qboolean ddshasalpha = false;
3248 float ddsavgcolor[4];
3249 char basename[MAX_QPATH];
3250 int miplevel = R_PicmipForFlags(textureflags);
3251 int savemiplevel = miplevel;
3254 if (cls.state == ca_dedicated)
3257 // return an existing skinframe if already loaded
3258 // if loading of the first image fails, don't make a new skinframe as it
3259 // would cause all future lookups of this to be missing
3260 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3261 if (skinframe && skinframe->base)
3264 Image_StripImageExtension(name, basename, sizeof(basename));
3266 // check for DDS texture file first
3267 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3269 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3270 if (basepixels == NULL)
3274 // FIXME handle miplevel
3276 if (developer_loading.integer)
3277 Con_Printf("loading skin \"%s\"\n", name);
3279 // we've got some pixels to store, so really allocate this new texture now
3281 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3282 skinframe->stain = NULL;
3283 skinframe->merged = NULL;
3284 skinframe->base = NULL;
3285 skinframe->pants = NULL;
3286 skinframe->shirt = NULL;
3287 skinframe->nmap = NULL;
3288 skinframe->gloss = NULL;
3289 skinframe->glow = NULL;
3290 skinframe->fog = NULL;
3291 skinframe->reflect = NULL;
3292 skinframe->hasalpha = false;
3296 skinframe->base = ddsbase;
3297 skinframe->hasalpha = ddshasalpha;
3298 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3299 if (r_loadfog && skinframe->hasalpha)
3300 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3301 //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]);
3305 basepixels_width = image_width;
3306 basepixels_height = image_height;
3307 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);
3308 if (textureflags & TEXF_ALPHA)
3310 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3312 if (basepixels[j] < 255)
3314 skinframe->hasalpha = true;
3318 if (r_loadfog && skinframe->hasalpha)
3320 // has transparent pixels
3321 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3322 for (j = 0;j < image_width * image_height * 4;j += 4)
3327 pixels[j+3] = basepixels[j+3];
3329 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);
3333 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3334 //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]);
3335 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3336 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3337 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3338 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3343 mymiplevel = savemiplevel;
3344 if (r_loadnormalmap)
3345 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);
3346 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3348 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3349 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3350 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3351 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3354 // _norm is the name used by tenebrae and has been adopted as standard
3355 if (r_loadnormalmap && skinframe->nmap == NULL)
3357 mymiplevel = savemiplevel;
3358 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3360 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);
3364 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3366 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3367 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3368 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);
3370 Mem_Free(bumppixels);
3372 else if (r_shadow_bumpscale_basetexture.value > 0)
3374 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3375 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3376 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);
3379 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3380 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3383 // _luma is supported only for tenebrae compatibility
3384 // _glow is the preferred name
3385 mymiplevel = savemiplevel;
3386 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))))
3388 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);
3389 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3390 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3391 Mem_Free(pixels);pixels = NULL;
3394 mymiplevel = savemiplevel;
3395 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3397 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);
3398 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3399 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3404 mymiplevel = savemiplevel;
3405 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3407 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);
3408 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3409 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3414 mymiplevel = savemiplevel;
3415 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3417 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);
3418 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3419 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3424 mymiplevel = savemiplevel;
3425 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3427 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);
3428 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3429 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3435 Mem_Free(basepixels);
3440 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3441 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3444 unsigned char *temp1, *temp2;
3445 skinframe_t *skinframe;
3447 if (cls.state == ca_dedicated)
3450 // if already loaded just return it, otherwise make a new skinframe
3451 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3452 if (skinframe && skinframe->base)
3455 skinframe->stain = NULL;
3456 skinframe->merged = NULL;
3457 skinframe->base = NULL;
3458 skinframe->pants = NULL;
3459 skinframe->shirt = NULL;
3460 skinframe->nmap = NULL;
3461 skinframe->gloss = NULL;
3462 skinframe->glow = NULL;
3463 skinframe->fog = NULL;
3464 skinframe->reflect = NULL;
3465 skinframe->hasalpha = false;
3467 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3471 if (developer_loading.integer)
3472 Con_Printf("loading 32bit skin \"%s\"\n", name);
3474 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3476 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3477 temp2 = temp1 + width * height * 4;
3478 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3479 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);
3482 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3483 if (textureflags & TEXF_ALPHA)
3485 for (i = 3;i < width * height * 4;i += 4)
3487 if (skindata[i] < 255)
3489 skinframe->hasalpha = true;
3493 if (r_loadfog && skinframe->hasalpha)
3495 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3496 memcpy(fogpixels, skindata, width * height * 4);
3497 for (i = 0;i < width * height * 4;i += 4)
3498 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3499 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3500 Mem_Free(fogpixels);
3504 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3505 //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]);
3510 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3514 skinframe_t *skinframe;
3516 if (cls.state == ca_dedicated)
3519 // if already loaded just return it, otherwise make a new skinframe
3520 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3521 if (skinframe && skinframe->base)
3524 skinframe->stain = NULL;
3525 skinframe->merged = NULL;
3526 skinframe->base = NULL;
3527 skinframe->pants = NULL;
3528 skinframe->shirt = NULL;
3529 skinframe->nmap = NULL;
3530 skinframe->gloss = NULL;
3531 skinframe->glow = NULL;
3532 skinframe->fog = NULL;
3533 skinframe->reflect = NULL;
3534 skinframe->hasalpha = false;
3536 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3540 if (developer_loading.integer)
3541 Con_Printf("loading quake skin \"%s\"\n", name);
3543 // 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)
3544 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3545 memcpy(skinframe->qpixels, skindata, width*height);
3546 skinframe->qwidth = width;
3547 skinframe->qheight = height;
3550 for (i = 0;i < width * height;i++)
3551 featuresmask |= palette_featureflags[skindata[i]];
3553 skinframe->hasalpha = false;
3554 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3555 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3556 skinframe->qgeneratemerged = true;
3557 skinframe->qgeneratebase = skinframe->qhascolormapping;
3558 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3560 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3561 //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]);
3566 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3570 unsigned char *skindata;
3572 if (!skinframe->qpixels)
3575 if (!skinframe->qhascolormapping)
3576 colormapped = false;
3580 if (!skinframe->qgeneratebase)
3585 if (!skinframe->qgeneratemerged)
3589 width = skinframe->qwidth;
3590 height = skinframe->qheight;
3591 skindata = skinframe->qpixels;
3593 if (skinframe->qgeneratenmap)
3595 unsigned char *temp1, *temp2;
3596 skinframe->qgeneratenmap = false;
3597 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3598 temp2 = temp1 + width * height * 4;
3599 // use either a custom palette or the quake palette
3600 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3601 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3602 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);
3606 if (skinframe->qgenerateglow)
3608 skinframe->qgenerateglow = false;
3609 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
3614 skinframe->qgeneratebase = false;
3615 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);
3616 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);
3617 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);
3621 skinframe->qgeneratemerged = false;
3622 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);
3625 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3627 Mem_Free(skinframe->qpixels);
3628 skinframe->qpixels = NULL;
3632 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)
3635 skinframe_t *skinframe;
3637 if (cls.state == ca_dedicated)
3640 // if already loaded just return it, otherwise make a new skinframe
3641 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3642 if (skinframe && skinframe->base)
3645 skinframe->stain = NULL;
3646 skinframe->merged = NULL;
3647 skinframe->base = NULL;
3648 skinframe->pants = NULL;
3649 skinframe->shirt = NULL;
3650 skinframe->nmap = NULL;
3651 skinframe->gloss = NULL;
3652 skinframe->glow = NULL;
3653 skinframe->fog = NULL;
3654 skinframe->reflect = NULL;
3655 skinframe->hasalpha = false;
3657 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3661 if (developer_loading.integer)
3662 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3664 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3665 if (textureflags & TEXF_ALPHA)
3667 for (i = 0;i < width * height;i++)
3669 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3671 skinframe->hasalpha = true;
3675 if (r_loadfog && skinframe->hasalpha)
3676 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3679 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3680 //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]);
3685 skinframe_t *R_SkinFrame_LoadMissing(void)
3687 skinframe_t *skinframe;
3689 if (cls.state == ca_dedicated)
3692 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3693 skinframe->stain = NULL;
3694 skinframe->merged = NULL;
3695 skinframe->base = NULL;
3696 skinframe->pants = NULL;
3697 skinframe->shirt = NULL;
3698 skinframe->nmap = NULL;
3699 skinframe->gloss = NULL;
3700 skinframe->glow = NULL;
3701 skinframe->fog = NULL;
3702 skinframe->reflect = NULL;
3703 skinframe->hasalpha = false;
3705 skinframe->avgcolor[0] = rand() / RAND_MAX;
3706 skinframe->avgcolor[1] = rand() / RAND_MAX;
3707 skinframe->avgcolor[2] = rand() / RAND_MAX;
3708 skinframe->avgcolor[3] = 1;
3713 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3714 typedef struct suffixinfo_s
3717 qboolean flipx, flipy, flipdiagonal;
3720 static suffixinfo_t suffix[3][6] =
3723 {"px", false, false, false},
3724 {"nx", false, false, false},
3725 {"py", false, false, false},
3726 {"ny", false, false, false},
3727 {"pz", false, false, false},
3728 {"nz", false, false, false}
3731 {"posx", false, false, false},
3732 {"negx", false, false, false},
3733 {"posy", false, false, false},
3734 {"negy", false, false, false},
3735 {"posz", false, false, false},
3736 {"negz", false, false, false}
3739 {"rt", true, false, true},
3740 {"lf", false, true, true},
3741 {"ft", true, true, false},
3742 {"bk", false, false, false},
3743 {"up", true, false, true},
3744 {"dn", true, false, true}
3748 static int componentorder[4] = {0, 1, 2, 3};
3750 rtexture_t *R_LoadCubemap(const char *basename)
3752 int i, j, cubemapsize;
3753 unsigned char *cubemappixels, *image_buffer;
3754 rtexture_t *cubemaptexture;
3756 // must start 0 so the first loadimagepixels has no requested width/height
3758 cubemappixels = NULL;
3759 cubemaptexture = NULL;
3760 // keep trying different suffix groups (posx, px, rt) until one loads
3761 for (j = 0;j < 3 && !cubemappixels;j++)
3763 // load the 6 images in the suffix group
3764 for (i = 0;i < 6;i++)
3766 // generate an image name based on the base and and suffix
3767 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3769 if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3771 // an image loaded, make sure width and height are equal
3772 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3774 // if this is the first image to load successfully, allocate the cubemap memory
3775 if (!cubemappixels && image_width >= 1)
3777 cubemapsize = image_width;
3778 // note this clears to black, so unavailable sides are black
3779 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3781 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3783 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);
3786 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3788 Mem_Free(image_buffer);
3792 // if a cubemap loaded, upload it
3795 if (developer_loading.integer)
3796 Con_Printf("loading cubemap \"%s\"\n", basename);
3798 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);
3799 Mem_Free(cubemappixels);
3803 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3804 if (developer_loading.integer)
3806 Con_Printf("(tried tried images ");
3807 for (j = 0;j < 3;j++)
3808 for (i = 0;i < 6;i++)
3809 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3810 Con_Print(" and was unable to find any of them).\n");
3813 return cubemaptexture;
3816 rtexture_t *R_GetCubemap(const char *basename)
3819 for (i = 0;i < r_texture_numcubemaps;i++)
3820 if (r_texture_cubemaps[i] != NULL)
3821 if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3822 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3823 if (i >= MAX_CUBEMAPS || !r_main_mempool)
3824 return r_texture_whitecube;
3825 r_texture_numcubemaps++;
3826 r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3827 strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3828 r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3829 return r_texture_cubemaps[i]->texture;
3832 void R_FreeCubemap(const char *basename)
3836 for (i = 0;i < r_texture_numcubemaps;i++)
3838 if (r_texture_cubemaps[i] != NULL)
3840 if (r_texture_cubemaps[i]->texture)
3842 if (developer_loading.integer)
3843 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3844 R_FreeTexture(r_texture_cubemaps[i]->texture);
3845 Mem_Free(r_texture_cubemaps[i]);
3846 r_texture_cubemaps[i] = NULL;
3852 void R_FreeCubemaps(void)
3855 for (i = 0;i < r_texture_numcubemaps;i++)
3857 if (developer_loading.integer)
3858 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3859 if (r_texture_cubemaps[i] != NULL)
3861 if (r_texture_cubemaps[i]->texture)
3862 R_FreeTexture(r_texture_cubemaps[i]->texture);
3863 Mem_Free(r_texture_cubemaps[i]);
3866 r_texture_numcubemaps = 0;
3869 void R_Main_FreeViewCache(void)
3871 if (r_refdef.viewcache.entityvisible)
3872 Mem_Free(r_refdef.viewcache.entityvisible);
3873 if (r_refdef.viewcache.world_pvsbits)
3874 Mem_Free(r_refdef.viewcache.world_pvsbits);
3875 if (r_refdef.viewcache.world_leafvisible)
3876 Mem_Free(r_refdef.viewcache.world_leafvisible);
3877 if (r_refdef.viewcache.world_surfacevisible)
3878 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3879 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3882 void R_Main_ResizeViewCache(void)
3884 int numentities = r_refdef.scene.numentities;
3885 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3886 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3887 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3888 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3889 if (r_refdef.viewcache.maxentities < numentities)
3891 r_refdef.viewcache.maxentities = numentities;
3892 if (r_refdef.viewcache.entityvisible)
3893 Mem_Free(r_refdef.viewcache.entityvisible);
3894 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3896 if (r_refdef.viewcache.world_numclusters != numclusters)
3898 r_refdef.viewcache.world_numclusters = numclusters;
3899 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3900 if (r_refdef.viewcache.world_pvsbits)
3901 Mem_Free(r_refdef.viewcache.world_pvsbits);
3902 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3904 if (r_refdef.viewcache.world_numleafs != numleafs)
3906 r_refdef.viewcache.world_numleafs = numleafs;
3907 if (r_refdef.viewcache.world_leafvisible)
3908 Mem_Free(r_refdef.viewcache.world_leafvisible);
3909 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3911 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3913 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3914 if (r_refdef.viewcache.world_surfacevisible)
3915 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3916 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3920 extern rtexture_t *loadingscreentexture;
3921 void gl_main_start(void)
3923 loadingscreentexture = NULL;
3924 r_texture_blanknormalmap = NULL;
3925 r_texture_white = NULL;
3926 r_texture_grey128 = NULL;
3927 r_texture_black = NULL;
3928 r_texture_whitecube = NULL;
3929 r_texture_normalizationcube = NULL;
3930 r_texture_fogattenuation = NULL;
3931 r_texture_fogheighttexture = NULL;
3932 r_texture_gammaramps = NULL;
3933 r_texture_numcubemaps = 0;
3935 r_loaddds = r_texture_dds_load.integer != 0;
3936 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3938 switch(vid.renderpath)
3940 case RENDERPATH_GL20:
3941 case RENDERPATH_D3D9:
3942 case RENDERPATH_D3D10:
3943 case RENDERPATH_D3D11:
3944 case RENDERPATH_SOFT:
3945 case RENDERPATH_GLES2:
3946 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3947 Cvar_SetValueQuick(&gl_combine, 1);
3948 Cvar_SetValueQuick(&r_glsl, 1);
3949 r_loadnormalmap = true;
3953 case RENDERPATH_GL13:
3954 case RENDERPATH_GLES1:
3955 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3956 Cvar_SetValueQuick(&gl_combine, 1);
3957 Cvar_SetValueQuick(&r_glsl, 0);
3958 r_loadnormalmap = false;
3959 r_loadgloss = false;
3962 case RENDERPATH_GL11:
3963 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3964 Cvar_SetValueQuick(&gl_combine, 0);
3965 Cvar_SetValueQuick(&r_glsl, 0);
3966 r_loadnormalmap = false;
3967 r_loadgloss = false;
3973 R_FrameData_Reset();
3977 memset(r_queries, 0, sizeof(r_queries));
3979 r_qwskincache = NULL;
3980 r_qwskincache_size = 0;
3982 // due to caching of texture_t references, the collision cache must be reset
3983 Collision_Cache_Reset(true);
3985 // set up r_skinframe loading system for textures
3986 memset(&r_skinframe, 0, sizeof(r_skinframe));
3987 r_skinframe.loadsequence = 1;
3988 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3990 r_main_texturepool = R_AllocTexturePool();
3991 R_BuildBlankTextures();
3993 if (vid.support.arb_texture_cube_map)
3996 R_BuildNormalizationCube();
3998 r_texture_fogattenuation = NULL;
3999 r_texture_fogheighttexture = NULL;
4000 r_texture_gammaramps = NULL;
4001 //r_texture_fogintensity = NULL;
4002 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4003 memset(&r_waterstate, 0, sizeof(r_waterstate));
4004 r_glsl_permutation = NULL;
4005 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4006 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4007 glslshaderstring = NULL;
4009 r_hlsl_permutation = NULL;
4010 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4011 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4013 hlslshaderstring = NULL;
4014 memset(&r_svbsp, 0, sizeof (r_svbsp));
4016 memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4017 r_texture_numcubemaps = 0;
4019 r_refdef.fogmasktable_density = 0;
4022 void gl_main_shutdown(void)
4025 R_FrameData_Reset();
4027 R_Main_FreeViewCache();
4029 switch(vid.renderpath)
4031 case RENDERPATH_GL11:
4032 case RENDERPATH_GL13:
4033 case RENDERPATH_GL20:
4034 case RENDERPATH_GLES1:
4035 case RENDERPATH_GLES2:
4037 qglDeleteQueriesARB(r_maxqueries, r_queries);
4039 case RENDERPATH_D3D9:
4040 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4042 case RENDERPATH_D3D10:
4043 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4045 case RENDERPATH_D3D11:
4046 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4048 case RENDERPATH_SOFT:
4054 memset(r_queries, 0, sizeof(r_queries));
4056 r_qwskincache = NULL;
4057 r_qwskincache_size = 0;
4059 // clear out the r_skinframe state
4060 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4061 memset(&r_skinframe, 0, sizeof(r_skinframe));
4064 Mem_Free(r_svbsp.nodes);
4065 memset(&r_svbsp, 0, sizeof (r_svbsp));
4066 R_FreeTexturePool(&r_main_texturepool);
4067 loadingscreentexture = NULL;
4068 r_texture_blanknormalmap = NULL;
4069 r_texture_white = NULL;
4070 r_texture_grey128 = NULL;
4071 r_texture_black = NULL;
4072 r_texture_whitecube = NULL;
4073 r_texture_normalizationcube = NULL;
4074 r_texture_fogattenuation = NULL;
4075 r_texture_fogheighttexture = NULL;
4076 r_texture_gammaramps = NULL;
4077 r_texture_numcubemaps = 0;
4078 //r_texture_fogintensity = NULL;
4079 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4080 memset(&r_waterstate, 0, sizeof(r_waterstate));
4083 r_glsl_permutation = NULL;
4084 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4085 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4086 glslshaderstring = NULL;
4088 r_hlsl_permutation = NULL;
4089 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4090 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4092 hlslshaderstring = NULL;
4095 extern void CL_ParseEntityLump(char *entitystring);
4096 void gl_main_newmap(void)
4098 // FIXME: move this code to client
4099 char *entities, entname[MAX_QPATH];
4101 Mem_Free(r_qwskincache);
4102 r_qwskincache = NULL;
4103 r_qwskincache_size = 0;
4106 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4107 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4109 CL_ParseEntityLump(entities);
4113 if (cl.worldmodel->brush.entities)
4114 CL_ParseEntityLump(cl.worldmodel->brush.entities);
4116 R_Main_FreeViewCache();
4118 R_FrameData_Reset();
4121 void GL_Main_Init(void)
4123 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4125 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4126 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4127 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4128 if (gamemode == GAME_NEHAHRA)
4130 Cvar_RegisterVariable (&gl_fogenable);
4131 Cvar_RegisterVariable (&gl_fogdensity);
4132 Cvar_RegisterVariable (&gl_fogred);
4133 Cvar_RegisterVariable (&gl_foggreen);
4134 Cvar_RegisterVariable (&gl_fogblue);
4135 Cvar_RegisterVariable (&gl_fogstart);
4136 Cvar_RegisterVariable (&gl_fogend);
4137 Cvar_RegisterVariable (&gl_skyclip);
4139 Cvar_RegisterVariable(&r_motionblur);
4140 Cvar_RegisterVariable(&r_motionblur_maxblur);
4141 Cvar_RegisterVariable(&r_motionblur_bmin);
4142 Cvar_RegisterVariable(&r_motionblur_vmin);
4143 Cvar_RegisterVariable(&r_motionblur_vmax);
4144 Cvar_RegisterVariable(&r_motionblur_vcoeff);
4145 Cvar_RegisterVariable(&r_motionblur_randomize);
4146 Cvar_RegisterVariable(&r_damageblur);
4147 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4148 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4149 Cvar_RegisterVariable(&r_equalize_entities_by);
4150 Cvar_RegisterVariable(&r_equalize_entities_to);
4151 Cvar_RegisterVariable(&r_depthfirst);
4152 Cvar_RegisterVariable(&r_useinfinitefarclip);
4153 Cvar_RegisterVariable(&r_farclip_base);
4154 Cvar_RegisterVariable(&r_farclip_world);
4155 Cvar_RegisterVariable(&r_nearclip);
4156 Cvar_RegisterVariable(&r_deformvertexes);
4157 Cvar_RegisterVariable(&r_transparent);
4158 Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4159 Cvar_RegisterVariable(&r_showoverdraw);
4160 Cvar_RegisterVariable(&r_showbboxes);
4161 Cvar_RegisterVariable(&r_showsurfaces);
4162 Cvar_RegisterVariable(&r_showtris);
4163 Cvar_RegisterVariable(&r_shownormals);
4164 Cvar_RegisterVariable(&r_showlighting);
4165 Cvar_RegisterVariable(&r_showshadowvolumes);
4166 Cvar_RegisterVariable(&r_showcollisionbrushes);
4167 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4168 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4169 Cvar_RegisterVariable(&r_showdisabledepthtest);
4170 Cvar_RegisterVariable(&r_drawportals);
4171 Cvar_RegisterVariable(&r_drawentities);
4172 Cvar_RegisterVariable(&r_draw2d);
4173 Cvar_RegisterVariable(&r_drawworld);
4174 Cvar_RegisterVariable(&r_cullentities_trace);
4175 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4176 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4177 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4178 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4179 Cvar_RegisterVariable(&r_drawviewmodel);
4180 Cvar_RegisterVariable(&r_drawexteriormodel);
4181 Cvar_RegisterVariable(&r_speeds);
4182 Cvar_RegisterVariable(&r_fullbrights);
4183 Cvar_RegisterVariable(&r_wateralpha);
4184 Cvar_RegisterVariable(&r_dynamic);
4185 Cvar_RegisterVariable(&r_fakelight);
4186 Cvar_RegisterVariable(&r_fakelight_intensity);
4187 Cvar_RegisterVariable(&r_fullbright);
4188 Cvar_RegisterVariable(&r_shadows);
4189 Cvar_RegisterVariable(&r_shadows_darken);
4190 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4191 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4192 Cvar_RegisterVariable(&r_shadows_throwdistance);
4193 Cvar_RegisterVariable(&r_shadows_throwdirection);
4194 Cvar_RegisterVariable(&r_shadows_focus);
4195 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4196 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4197 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4198 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4199 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4200 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4201 Cvar_RegisterVariable(&r_fog_exp2);
4202 Cvar_RegisterVariable(&r_fog_clear);
4203 Cvar_RegisterVariable(&r_drawfog);
4204 Cvar_RegisterVariable(&r_transparentdepthmasking);
4205 Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4206 Cvar_RegisterVariable(&r_transparent_sortarraysize);
4207 Cvar_RegisterVariable(&r_texture_dds_load);
4208 Cvar_RegisterVariable(&r_texture_dds_save);
4209 Cvar_RegisterVariable(&r_textureunits);
4210 Cvar_RegisterVariable(&gl_combine);
4211 Cvar_RegisterVariable(&r_viewfbo);
4212 Cvar_RegisterVariable(&r_viewscale);
4213 Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4214 Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4215 Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4216 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4217 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4218 Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4219 Cvar_RegisterVariable(&r_glsl);
4220 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4221 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4222 Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4223 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4224 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4225 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4226 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4227 Cvar_RegisterVariable(&r_glsl_postprocess);
4228 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4229 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4230 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4231 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4232 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4233 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4234 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4235 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4237 Cvar_RegisterVariable(&r_water);
4238 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4239 Cvar_RegisterVariable(&r_water_clippingplanebias);
4240 Cvar_RegisterVariable(&r_water_refractdistort);
4241 Cvar_RegisterVariable(&r_water_reflectdistort);
4242 Cvar_RegisterVariable(&r_water_scissormode);
4243 Cvar_RegisterVariable(&r_water_lowquality);
4245 Cvar_RegisterVariable(&r_lerpsprites);
4246 Cvar_RegisterVariable(&r_lerpmodels);
4247 Cvar_RegisterVariable(&r_lerplightstyles);
4248 Cvar_RegisterVariable(&r_waterscroll);
4249 Cvar_RegisterVariable(&r_bloom);
4250 Cvar_RegisterVariable(&r_bloom_colorscale);
4251 Cvar_RegisterVariable(&r_bloom_brighten);
4252 Cvar_RegisterVariable(&r_bloom_blur);
4253 Cvar_RegisterVariable(&r_bloom_resolution);
4254 Cvar_RegisterVariable(&r_bloom_colorexponent);
4255 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4256 Cvar_RegisterVariable(&r_hdr);
4257 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4258 Cvar_RegisterVariable(&r_hdr_glowintensity);
4259 Cvar_RegisterVariable(&r_hdr_range);
4260 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4261 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4262 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4263 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4264 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4265 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4266 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4267 Cvar_RegisterVariable(&developer_texturelogging);
4268 Cvar_RegisterVariable(&gl_lightmaps);
4269 Cvar_RegisterVariable(&r_test);
4270 Cvar_RegisterVariable(&r_glsl_saturation);
4271 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4272 Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4273 Cvar_RegisterVariable(&r_framedatasize);
4274 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4275 Cvar_SetValue("r_fullbrights", 0);
4276 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4279 extern void R_Textures_Init(void);
4280 extern void GL_Draw_Init(void);
4281 extern void GL_Main_Init(void);
4282 extern void R_Shadow_Init(void);
4283 extern void R_Sky_Init(void);
4284 extern void GL_Surf_Init(void);
4285 extern void R_Particles_Init(void);
4286 extern void R_Explosion_Init(void);
4287 extern void gl_backend_init(void);
4288 extern void Sbar_Init(void);
4289 extern void R_LightningBeams_Init(void);
4290 extern void Mod_RenderInit(void);
4291 extern void Font_Init(void);
4293 void Render_Init(void)
4306 R_LightningBeams_Init();
4315 extern char *ENGINE_EXTENSIONS;
4318 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4319 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4320 gl_version = (const char *)qglGetString(GL_VERSION);
4321 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4325 if (!gl_platformextensions)
4326 gl_platformextensions = "";
4328 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4329 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4330 Con_Printf("GL_VERSION: %s\n", gl_version);
4331 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4332 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4334 VID_CheckExtensions();
4336 // LordHavoc: report supported extensions
4337 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4339 // clear to black (loading plaque will be seen over this)
4340 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4343 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4347 if (r_trippy.integer)
4349 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4351 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4354 p = r_refdef.view.frustum + i;
4359 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4363 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4367 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4371 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4375 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4379 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4383 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4387 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4395 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4399 if (r_trippy.integer)
4401 for (i = 0;i < numplanes;i++)
4408 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4412 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4416 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4420 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4424 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4428 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4432 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4436 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4444 //==================================================================================
4446 // LordHavoc: this stores temporary data used within the same frame
4448 typedef struct r_framedata_mem_s
4450 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4451 size_t size; // how much usable space
4452 size_t current; // how much space in use
4453 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4454 size_t wantedsize; // how much space was allocated
4455 unsigned char *data; // start of real data (16byte aligned)
4459 static r_framedata_mem_t *r_framedata_mem;
4461 void R_FrameData_Reset(void)
4463 while (r_framedata_mem)
4465 r_framedata_mem_t *next = r_framedata_mem->purge;
4466 Mem_Free(r_framedata_mem);
4467 r_framedata_mem = next;
4471 void R_FrameData_Resize(void)
4474 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4475 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4476 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4478 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4479 newmem->wantedsize = wantedsize;
4480 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4481 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4482 newmem->current = 0;
4484 newmem->purge = r_framedata_mem;
4485 r_framedata_mem = newmem;
4489 void R_FrameData_NewFrame(void)
4491 R_FrameData_Resize();
4492 if (!r_framedata_mem)
4494 // if we ran out of space on the last frame, free the old memory now
4495 while (r_framedata_mem->purge)
4497 // repeatedly remove the second item in the list, leaving only head
4498 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4499 Mem_Free(r_framedata_mem->purge);
4500 r_framedata_mem->purge = next;
4502 // reset the current mem pointer
4503 r_framedata_mem->current = 0;
4504 r_framedata_mem->mark = 0;
4507 void *R_FrameData_Alloc(size_t size)
4511 // align to 16 byte boundary - the data pointer is already aligned, so we
4512 // only need to ensure the size of every allocation is also aligned
4513 size = (size + 15) & ~15;
4515 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4517 // emergency - we ran out of space, allocate more memory
4518 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4519 R_FrameData_Resize();
4522 data = r_framedata_mem->data + r_framedata_mem->current;
4523 r_framedata_mem->current += size;
4525 // count the usage for stats
4526 r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4527 r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4529 return (void *)data;
4532 void *R_FrameData_Store(size_t size, void *data)
4534 void *d = R_FrameData_Alloc(size);
4536 memcpy(d, data, size);
4540 void R_FrameData_SetMark(void)
4542 if (!r_framedata_mem)
4544 r_framedata_mem->mark = r_framedata_mem->current;
4547 void R_FrameData_ReturnToMark(void)
4549 if (!r_framedata_mem)
4551 r_framedata_mem->current = r_framedata_mem->mark;
4554 //==================================================================================
4556 // LordHavoc: animcache originally written by Echon, rewritten since then
4559 * Animation cache prevents re-generating mesh data for an animated model
4560 * multiple times in one frame for lighting, shadowing, reflections, etc.
4563 void R_AnimCache_Free(void)
4567 void R_AnimCache_ClearCache(void)
4570 entity_render_t *ent;
4572 for (i = 0;i < r_refdef.scene.numentities;i++)
4574 ent = r_refdef.scene.entities[i];
4575 ent->animcache_vertex3f = NULL;
4576 ent->animcache_normal3f = NULL;
4577 ent->animcache_svector3f = NULL;
4578 ent->animcache_tvector3f = NULL;
4579 ent->animcache_vertexmesh = NULL;
4580 ent->animcache_vertex3fbuffer = NULL;
4581 ent->animcache_vertexmeshbuffer = NULL;
4585 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4589 // check if we need the meshbuffers
4590 if (!vid.useinterleavedarrays)
4593 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4594 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4595 // TODO: upload vertex3f buffer?
4596 if (ent->animcache_vertexmesh)
4598 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4599 for (i = 0;i < numvertices;i++)
4600 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4601 if (ent->animcache_svector3f)
4602 for (i = 0;i < numvertices;i++)
4603 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4604 if (ent->animcache_tvector3f)
4605 for (i = 0;i < numvertices;i++)
4606 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4607 if (ent->animcache_normal3f)
4608 for (i = 0;i < numvertices;i++)
4609 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4610 // TODO: upload vertexmeshbuffer?
4614 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4616 dp_model_t *model = ent->model;
4618 // see if it's already cached this frame
4619 if (ent->animcache_vertex3f)
4621 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4622 if (wantnormals || wanttangents)
4624 if (ent->animcache_normal3f)
4625 wantnormals = false;
4626 if (ent->animcache_svector3f)
4627 wanttangents = false;
4628 if (wantnormals || wanttangents)
4630 numvertices = model->surfmesh.num_vertices;
4632 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4635 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4636 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4638 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4639 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4645 // see if this ent is worth caching
4646 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4648 // get some memory for this entity and generate mesh data
4649 numvertices = model->surfmesh.num_vertices;
4650 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4652 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4655 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4656 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4658 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4659 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4664 void R_AnimCache_CacheVisibleEntities(void)
4667 qboolean wantnormals = true;
4668 qboolean wanttangents = !r_showsurfaces.integer;
4670 switch(vid.renderpath)
4672 case RENDERPATH_GL20:
4673 case RENDERPATH_D3D9:
4674 case RENDERPATH_D3D10:
4675 case RENDERPATH_D3D11:
4676 case RENDERPATH_GLES2:
4678 case RENDERPATH_GL11:
4679 case RENDERPATH_GL13:
4680 case RENDERPATH_GLES1:
4681 wanttangents = false;
4683 case RENDERPATH_SOFT:
4687 if (r_shownormals.integer)
4688 wanttangents = wantnormals = true;
4690 // TODO: thread this
4691 // NOTE: R_PrepareRTLights() also caches entities
4693 for (i = 0;i < r_refdef.scene.numentities;i++)
4694 if (r_refdef.viewcache.entityvisible[i])
4695 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4698 //==================================================================================
4700 extern cvar_t r_overheadsprites_pushback;
4702 static void R_View_UpdateEntityLighting (void)
4705 entity_render_t *ent;
4706 vec3_t tempdiffusenormal, avg;
4707 vec_t f, fa, fd, fdd;
4708 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4710 for (i = 0;i < r_refdef.scene.numentities;i++)
4712 ent = r_refdef.scene.entities[i];
4714 // skip unseen models
4715 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4719 if (ent->model && ent->model->brush.num_leafs)
4721 // TODO: use modellight for r_ambient settings on world?
4722 VectorSet(ent->modellight_ambient, 0, 0, 0);
4723 VectorSet(ent->modellight_diffuse, 0, 0, 0);
4724 VectorSet(ent->modellight_lightdir, 0, 0, 1);
4728 // fetch the lighting from the worldmodel data
4729 VectorClear(ent->modellight_ambient);
4730 VectorClear(ent->modellight_diffuse);
4731 VectorClear(tempdiffusenormal);
4732 if (ent->flags & RENDER_LIGHT)
4735 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4737 // complete lightning for lit sprites
4738 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4739 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4741 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4742 org[2] = org[2] + r_overheadsprites_pushback.value;
4743 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4746 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4748 if(ent->flags & RENDER_EQUALIZE)
4750 // first fix up ambient lighting...
4751 if(r_equalize_entities_minambient.value > 0)
4753 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4756 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4757 if(fa < r_equalize_entities_minambient.value * fd)
4760 // fa'/fd' = minambient
4761 // fa'+0.25*fd' = fa+0.25*fd
4763 // fa' = fd' * minambient
4764 // fd'*(0.25+minambient) = fa+0.25*fd
4766 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4767 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4769 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4770 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
4771 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4772 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4777 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4779 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4780 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4784 // adjust brightness and saturation to target
4785 avg[0] = avg[1] = avg[2] = fa / f;
4786 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4787 avg[0] = avg[1] = avg[2] = fd / f;
4788 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4794 VectorSet(ent->modellight_ambient, 1, 1, 1);
4796 // move the light direction into modelspace coordinates for lighting code
4797 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4798 if(VectorLength2(ent->modellight_lightdir) == 0)
4799 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4800 VectorNormalize(ent->modellight_lightdir);
4804 #define MAX_LINEOFSIGHTTRACES 64
4806 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4809 vec3_t boxmins, boxmaxs;
4812 dp_model_t *model = r_refdef.scene.worldmodel;
4814 if (!model || !model->brush.TraceLineOfSight)
4817 // expand the box a little
4818 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4819 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4820 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4821 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4822 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4823 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4825 // return true if eye is inside enlarged box
4826 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4830 VectorCopy(eye, start);
4831 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4832 if (model->brush.TraceLineOfSight(model, start, end))
4835 // try various random positions
4836 for (i = 0;i < numsamples;i++)
4838 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4839 if (model->brush.TraceLineOfSight(model, start, end))
4847 static void R_View_UpdateEntityVisible (void)
4852 entity_render_t *ent;
4854 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4855 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4856 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
4857 : RENDER_EXTERIORMODEL;
4858 if (!r_drawviewmodel.integer)
4859 renderimask |= RENDER_VIEWMODEL;
4860 if (!r_drawexteriormodel.integer)
4861 renderimask |= RENDER_EXTERIORMODEL;
4862 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4864 // worldmodel can check visibility
4865 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4866 for (i = 0;i < r_refdef.scene.numentities;i++)
4868 ent = r_refdef.scene.entities[i];
4869 if (!(ent->flags & renderimask))
4870 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)))
4871 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))
4872 r_refdef.viewcache.entityvisible[i] = true;
4877 // no worldmodel or it can't check visibility
4878 for (i = 0;i < r_refdef.scene.numentities;i++)
4880 ent = r_refdef.scene.entities[i];
4881 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));
4884 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
4885 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4887 for (i = 0;i < r_refdef.scene.numentities;i++)
4889 if (!r_refdef.viewcache.entityvisible[i])
4891 ent = r_refdef.scene.entities[i];
4892 if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4894 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4896 continue; // temp entities do pvs only
4897 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4898 ent->last_trace_visibility = realtime;
4899 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4900 r_refdef.viewcache.entityvisible[i] = 0;
4906 /// only used if skyrendermasked, and normally returns false
4907 int R_DrawBrushModelsSky (void)
4910 entity_render_t *ent;
4913 for (i = 0;i < r_refdef.scene.numentities;i++)
4915 if (!r_refdef.viewcache.entityvisible[i])
4917 ent = r_refdef.scene.entities[i];
4918 if (!ent->model || !ent->model->DrawSky)
4920 ent->model->DrawSky(ent);
4926 static void R_DrawNoModel(entity_render_t *ent);
4927 static void R_DrawModels(void)
4930 entity_render_t *ent;
4932 for (i = 0;i < r_refdef.scene.numentities;i++)
4934 if (!r_refdef.viewcache.entityvisible[i])
4936 ent = r_refdef.scene.entities[i];
4937 r_refdef.stats.entities++;
4939 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
4942 Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
4943 Con_Printf("R_DrawModels\n");
4944 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]);
4945 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);
4946 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);
4949 if (ent->model && ent->model->Draw != NULL)
4950 ent->model->Draw(ent);
4956 static void R_DrawModelsDepth(void)
4959 entity_render_t *ent;
4961 for (i = 0;i < r_refdef.scene.numentities;i++)
4963 if (!r_refdef.viewcache.entityvisible[i])
4965 ent = r_refdef.scene.entities[i];
4966 if (ent->model && ent->model->DrawDepth != NULL)
4967 ent->model->DrawDepth(ent);
4971 static void R_DrawModelsDebug(void)
4974 entity_render_t *ent;
4976 for (i = 0;i < r_refdef.scene.numentities;i++)
4978 if (!r_refdef.viewcache.entityvisible[i])
4980 ent = r_refdef.scene.entities[i];
4981 if (ent->model && ent->model->DrawDebug != NULL)
4982 ent->model->DrawDebug(ent);
4986 static void R_DrawModelsAddWaterPlanes(void)
4989 entity_render_t *ent;
4991 for (i = 0;i < r_refdef.scene.numentities;i++)
4993 if (!r_refdef.viewcache.entityvisible[i])
4995 ent = r_refdef.scene.entities[i];
4996 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4997 ent->model->DrawAddWaterPlanes(ent);
5001 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5003 if (r_hdr_irisadaptation.integer)
5007 vec3_t diffusenormal;
5012 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5013 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
5014 brightness = max(0.0000001f, brightness);
5015 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5016 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5017 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
5018 current = r_hdr_irisadaptation_value.value;
5020 current = min(current + adjust, goal);
5021 else if (current > goal)
5022 current = max(current - adjust, goal);
5023 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5024 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5026 else if (r_hdr_irisadaptation_value.value != 1.0f)
5027 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5030 static void R_View_SetFrustum(const int *scissor)
5033 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5034 vec3_t forward, left, up, origin, v;
5038 // flipped x coordinates (because x points left here)
5039 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5040 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5042 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5043 switch(vid.renderpath)
5045 case RENDERPATH_D3D9:
5046 case RENDERPATH_D3D10:
5047 case RENDERPATH_D3D11:
5048 // non-flipped y coordinates
5049 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5050 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5052 case RENDERPATH_SOFT:
5053 case RENDERPATH_GL11:
5054 case RENDERPATH_GL13:
5055 case RENDERPATH_GL20:
5056 case RENDERPATH_GLES1:
5057 case RENDERPATH_GLES2:
5058 // non-flipped y coordinates
5059 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5060 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5065 // we can't trust r_refdef.view.forward and friends in reflected scenes
5066 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5069 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5070 r_refdef.view.frustum[0].normal[1] = 0 - 0;
5071 r_refdef.view.frustum[0].normal[2] = -1 - 0;
5072 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5073 r_refdef.view.frustum[1].normal[1] = 0 + 0;
5074 r_refdef.view.frustum[1].normal[2] = -1 + 0;
5075 r_refdef.view.frustum[2].normal[0] = 0 - 0;
5076 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5077 r_refdef.view.frustum[2].normal[2] = -1 - 0;
5078 r_refdef.view.frustum[3].normal[0] = 0 + 0;
5079 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5080 r_refdef.view.frustum[3].normal[2] = -1 + 0;
5084 zNear = r_refdef.nearclip;
5085 nudge = 1.0 - 1.0 / (1<<23);
5086 r_refdef.view.frustum[4].normal[0] = 0 - 0;
5087 r_refdef.view.frustum[4].normal[1] = 0 - 0;
5088 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5089 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5090 r_refdef.view.frustum[5].normal[0] = 0 + 0;
5091 r_refdef.view.frustum[5].normal[1] = 0 + 0;
5092 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5093 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5099 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5100 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5101 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5102 r_refdef.view.frustum[0].dist = m[15] - m[12];
5104 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5105 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5106 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5107 r_refdef.view.frustum[1].dist = m[15] + m[12];
5109 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5110 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5111 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5112 r_refdef.view.frustum[2].dist = m[15] - m[13];
5114 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5115 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5116 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5117 r_refdef.view.frustum[3].dist = m[15] + m[13];
5119 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5120 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5121 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5122 r_refdef.view.frustum[4].dist = m[15] - m[14];
5124 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5125 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5126 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5127 r_refdef.view.frustum[5].dist = m[15] + m[14];
5130 if (r_refdef.view.useperspective)
5132 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5133 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]);
5134 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]);
5135 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]);
5136 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]);
5138 // then the normals from the corners relative to origin
5139 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5140 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5141 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5142 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5144 // in a NORMAL view, forward cross left == up
5145 // in a REFLECTED view, forward cross left == down
5146 // so our cross products above need to be adjusted for a left handed coordinate system
5147 CrossProduct(forward, left, v);
5148 if(DotProduct(v, up) < 0)
5150 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5151 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5152 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5153 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5156 // Leaving those out was a mistake, those were in the old code, and they
5157 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5158 // I couldn't reproduce it after adding those normalizations. --blub
5159 VectorNormalize(r_refdef.view.frustum[0].normal);
5160 VectorNormalize(r_refdef.view.frustum[1].normal);
5161 VectorNormalize(r_refdef.view.frustum[2].normal);
5162 VectorNormalize(r_refdef.view.frustum[3].normal);
5164 // make the corners absolute
5165 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5166 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5167 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5168 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5171 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5173 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5174 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5175 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5176 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5177 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5181 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5182 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5183 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5184 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5185 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5186 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5187 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5188 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5189 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5190 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5192 r_refdef.view.numfrustumplanes = 5;
5194 if (r_refdef.view.useclipplane)
5196 r_refdef.view.numfrustumplanes = 6;
5197 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5200 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5201 PlaneClassify(r_refdef.view.frustum + i);
5203 // LordHavoc: note to all quake engine coders, Quake had a special case
5204 // for 90 degrees which assumed a square view (wrong), so I removed it,
5205 // Quake2 has it disabled as well.
5207 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5208 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5209 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5210 //PlaneClassify(&frustum[0]);
5212 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5213 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5214 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5215 //PlaneClassify(&frustum[1]);
5217 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5218 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5219 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5220 //PlaneClassify(&frustum[2]);
5222 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5223 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5224 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5225 //PlaneClassify(&frustum[3]);
5228 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5229 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5230 //PlaneClassify(&frustum[4]);
5233 void R_View_UpdateWithScissor(const int *myscissor)
5235 R_Main_ResizeViewCache();
5236 R_View_SetFrustum(myscissor);
5237 R_View_WorldVisibility(r_refdef.view.useclipplane);
5238 R_View_UpdateEntityVisible();
5239 R_View_UpdateEntityLighting();
5242 void R_View_Update(void)
5244 R_Main_ResizeViewCache();
5245 R_View_SetFrustum(NULL);
5246 R_View_WorldVisibility(r_refdef.view.useclipplane);
5247 R_View_UpdateEntityVisible();
5248 R_View_UpdateEntityLighting();
5251 float viewscalefpsadjusted = 1.0f;
5253 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5255 float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5256 scale = bound(0.03125f, scale, 1.0f);
5257 *outwidth = (int)ceil(width * scale);
5258 *outheight = (int)ceil(height * scale);
5261 void R_Mesh_SetMainRenderTargets(void)
5263 if (r_bloomstate.fbo_framebuffer)
5264 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5266 R_Mesh_ResetRenderTargets();
5269 void R_SetupView(qboolean allowwaterclippingplane)
5271 const float *customclipplane = NULL;
5273 int scaledwidth, scaledheight;
5274 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5276 // LordHavoc: couldn't figure out how to make this approach the
5277 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5278 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5279 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5280 dist = r_refdef.view.clipplane.dist;
5281 plane[0] = r_refdef.view.clipplane.normal[0];
5282 plane[1] = r_refdef.view.clipplane.normal[1];
5283 plane[2] = r_refdef.view.clipplane.normal[2];
5285 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5288 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5289 if (!r_refdef.view.useperspective)
5290 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);
5291 else if (vid.stencil && r_useinfinitefarclip.integer)
5292 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);
5294 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);
5295 R_Mesh_SetMainRenderTargets();
5296 R_SetViewport(&r_refdef.view.viewport);
5297 if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5299 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5300 float screenplane[4];
5301 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5302 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5303 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5304 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5305 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5309 void R_EntityMatrix(const matrix4x4_t *matrix)
5311 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5313 gl_modelmatrixchanged = false;
5314 gl_modelmatrix = *matrix;
5315 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5316 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5317 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5318 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5320 switch(vid.renderpath)
5322 case RENDERPATH_D3D9:
5324 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5325 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5328 case RENDERPATH_D3D10:
5329 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5331 case RENDERPATH_D3D11:
5332 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5334 case RENDERPATH_GL11:
5335 case RENDERPATH_GL13:
5336 case RENDERPATH_GLES1:
5337 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5339 case RENDERPATH_SOFT:
5340 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5341 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5343 case RENDERPATH_GL20:
5344 case RENDERPATH_GLES2:
5345 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5346 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5352 void R_ResetViewRendering2D(void)
5354 r_viewport_t viewport;
5357 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5358 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);
5359 R_Mesh_ResetRenderTargets();
5360 R_SetViewport(&viewport);
5361 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5362 GL_Color(1, 1, 1, 1);
5363 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5364 GL_BlendFunc(GL_ONE, GL_ZERO);
5365 GL_ScissorTest(false);
5366 GL_DepthMask(false);
5367 GL_DepthRange(0, 1);
5368 GL_DepthTest(false);
5369 GL_DepthFunc(GL_LEQUAL);
5370 R_EntityMatrix(&identitymatrix);
5371 R_Mesh_ResetTextureState();
5372 GL_PolygonOffset(0, 0);
5373 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5374 switch(vid.renderpath)
5376 case RENDERPATH_GL11:
5377 case RENDERPATH_GL13:
5378 case RENDERPATH_GL20:
5379 case RENDERPATH_GLES1:
5380 case RENDERPATH_GLES2:
5381 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5383 case RENDERPATH_D3D9:
5384 case RENDERPATH_D3D10:
5385 case RENDERPATH_D3D11:
5386 case RENDERPATH_SOFT:
5389 GL_CullFace(GL_NONE);
5392 void R_ResetViewRendering3D(void)
5397 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5398 GL_Color(1, 1, 1, 1);
5399 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5400 GL_BlendFunc(GL_ONE, GL_ZERO);
5401 GL_ScissorTest(true);
5403 GL_DepthRange(0, 1);
5405 GL_DepthFunc(GL_LEQUAL);
5406 R_EntityMatrix(&identitymatrix);
5407 R_Mesh_ResetTextureState();
5408 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5409 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5410 switch(vid.renderpath)
5412 case RENDERPATH_GL11:
5413 case RENDERPATH_GL13:
5414 case RENDERPATH_GL20:
5415 case RENDERPATH_GLES1:
5416 case RENDERPATH_GLES2:
5417 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5419 case RENDERPATH_D3D9:
5420 case RENDERPATH_D3D10:
5421 case RENDERPATH_D3D11:
5422 case RENDERPATH_SOFT:
5425 GL_CullFace(r_refdef.view.cullface_back);
5430 R_RenderView_UpdateViewVectors
5433 static void R_RenderView_UpdateViewVectors(void)
5435 // break apart the view matrix into vectors for various purposes
5436 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5437 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5438 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5439 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5440 // make an inverted copy of the view matrix for tracking sprites
5441 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5444 void R_RenderScene(void);
5445 void R_RenderWaterPlanes(void);
5447 static void R_Water_StartFrame(void)
5450 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5451 r_waterstate_waterplane_t *p;
5453 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5456 switch(vid.renderpath)
5458 case RENDERPATH_GL20:
5459 case RENDERPATH_D3D9:
5460 case RENDERPATH_D3D10:
5461 case RENDERPATH_D3D11:
5462 case RENDERPATH_SOFT:
5463 case RENDERPATH_GLES2:
5465 case RENDERPATH_GL11:
5466 case RENDERPATH_GL13:
5467 case RENDERPATH_GLES1:
5471 // set waterwidth and waterheight to the water resolution that will be
5472 // used (often less than the screen resolution for faster rendering)
5473 R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5475 // calculate desired texture sizes
5476 // can't use water if the card does not support the texture size
5477 if (!r_water.integer || r_showsurfaces.integer)
5478 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5479 else if (vid.support.arb_texture_non_power_of_two)
5481 texturewidth = waterwidth;
5482 textureheight = waterheight;
5483 camerawidth = waterwidth;
5484 cameraheight = waterheight;
5488 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5489 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5490 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
5491 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
5494 // allocate textures as needed
5495 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5497 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5498 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5500 if (p->texture_refraction)
5501 R_FreeTexture(p->texture_refraction);
5502 p->texture_refraction = NULL;
5503 if (p->texture_reflection)
5504 R_FreeTexture(p->texture_reflection);
5505 p->texture_reflection = NULL;
5506 if (p->texture_camera)
5507 R_FreeTexture(p->texture_camera);
5508 p->texture_camera = NULL;
5510 memset(&r_waterstate, 0, sizeof(r_waterstate));
5511 r_waterstate.texturewidth = texturewidth;
5512 r_waterstate.textureheight = textureheight;
5513 r_waterstate.camerawidth = camerawidth;
5514 r_waterstate.cameraheight = cameraheight;
5517 if (r_waterstate.texturewidth)
5519 int scaledwidth, scaledheight;
5521 r_waterstate.enabled = true;
5523 // when doing a reduced render (HDR) we want to use a smaller area
5524 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5525 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5526 R_GetScaledViewSize(r_waterstate.waterwidth, r_waterstate.waterheight, &scaledwidth, &scaledheight);
5528 // set up variables that will be used in shader setup
5529 r_waterstate.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5530 r_waterstate.screenscale[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5531 r_waterstate.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5532 r_waterstate.screencenter[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5535 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5536 r_waterstate.numwaterplanes = 0;
5539 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5541 int triangleindex, planeindex;
5547 r_waterstate_waterplane_t *p;
5548 texture_t *t = R_GetCurrentTexture(surface->texture);
5550 // just use the first triangle with a valid normal for any decisions
5551 VectorClear(normal);
5552 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5554 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5555 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5556 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5557 TriangleNormal(vert[0], vert[1], vert[2], normal);
5558 if (VectorLength2(normal) >= 0.001)
5562 VectorCopy(normal, plane.normal);
5563 VectorNormalize(plane.normal);
5564 plane.dist = DotProduct(vert[0], plane.normal);
5565 PlaneClassify(&plane);
5566 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5568 // skip backfaces (except if nocullface is set)
5569 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5571 VectorNegate(plane.normal, plane.normal);
5573 PlaneClassify(&plane);
5577 // find a matching plane if there is one
5578 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5579 if(p->camera_entity == t->camera_entity)
5580 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5582 if (planeindex >= r_waterstate.maxwaterplanes)
5583 return; // nothing we can do, out of planes
5585 // if this triangle does not fit any known plane rendered this frame, add one
5586 if (planeindex >= r_waterstate.numwaterplanes)
5588 // store the new plane
5589 r_waterstate.numwaterplanes++;
5591 // clear materialflags and pvs
5592 p->materialflags = 0;
5593 p->pvsvalid = false;
5594 p->camera_entity = t->camera_entity;
5595 VectorCopy(surface->mins, p->mins);
5596 VectorCopy(surface->maxs, p->maxs);
5601 p->mins[0] = min(p->mins[0], surface->mins[0]);
5602 p->mins[1] = min(p->mins[1], surface->mins[1]);
5603 p->mins[2] = min(p->mins[2], surface->mins[2]);
5604 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5605 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5606 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5608 // merge this surface's materialflags into the waterplane
5609 p->materialflags |= t->currentmaterialflags;
5610 if(!(p->materialflags & MATERIALFLAG_CAMERA))
5612 // merge this surface's PVS into the waterplane
5613 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5614 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5615 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5617 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5623 extern cvar_t r_drawparticles;
5624 extern cvar_t r_drawdecals;
5626 static void R_Water_ProcessPlanes(void)
5629 r_refdef_view_t originalview;
5630 r_refdef_view_t myview;
5631 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;
5632 r_waterstate_waterplane_t *p;
5635 originalview = r_refdef.view;
5637 // lowquality hack, temporarily shut down some cvars and restore afterwards
5638 qualityreduction = r_water_lowquality.integer;
5639 if (qualityreduction > 0)
5641 if (qualityreduction >= 1)
5643 old_r_shadows = r_shadows.integer;
5644 old_r_worldrtlight = r_shadow_realtime_world.integer;
5645 old_r_dlight = r_shadow_realtime_dlight.integer;
5646 Cvar_SetValueQuick(&r_shadows, 0);
5647 Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5648 Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5650 if (qualityreduction >= 2)
5652 old_r_dynamic = r_dynamic.integer;
5653 old_r_particles = r_drawparticles.integer;
5654 old_r_decals = r_drawdecals.integer;
5655 Cvar_SetValueQuick(&r_dynamic, 0);
5656 Cvar_SetValueQuick(&r_drawparticles, 0);
5657 Cvar_SetValueQuick(&r_drawdecals, 0);
5661 // make sure enough textures are allocated
5662 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5664 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5666 if (!p->texture_refraction)
5667 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);
5668 if (!p->texture_refraction)
5671 else if (p->materialflags & MATERIALFLAG_CAMERA)
5673 if (!p->texture_camera)
5674 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);
5675 if (!p->texture_camera)
5679 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5681 if (!p->texture_reflection)
5682 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);
5683 if (!p->texture_reflection)
5689 r_refdef.view = originalview;
5690 r_refdef.view.showdebug = false;
5691 r_refdef.view.width = r_waterstate.waterwidth;
5692 r_refdef.view.height = r_waterstate.waterheight;
5693 r_refdef.view.useclipplane = true;
5694 myview = r_refdef.view;
5695 r_waterstate.renderingscene = true;
5696 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5698 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5700 r_refdef.view = myview;
5701 if(r_water_scissormode.integer)
5704 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5705 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5708 // render reflected scene and copy into texture
5709 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5710 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5711 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5712 r_refdef.view.clipplane = p->plane;
5713 // reverse the cullface settings for this render
5714 r_refdef.view.cullface_front = GL_FRONT;
5715 r_refdef.view.cullface_back = GL_BACK;
5716 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5718 r_refdef.view.usecustompvs = true;
5720 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5722 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5725 R_ResetViewRendering3D();
5726 R_ClearScreen(r_refdef.fogenabled);
5727 if(r_water_scissormode.integer & 2)
5728 R_View_UpdateWithScissor(myscissor);
5731 if(r_water_scissormode.integer & 1)
5732 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5735 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);
5738 // render the normal view scene and copy into texture
5739 // (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)
5740 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5742 r_refdef.view = myview;
5743 if(r_water_scissormode.integer)
5746 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5747 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5750 r_waterstate.renderingrefraction = true;
5752 r_refdef.view.clipplane = p->plane;
5753 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5754 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5756 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5758 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5759 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5760 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5761 R_RenderView_UpdateViewVectors();
5762 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5764 r_refdef.view.usecustompvs = true;
5765 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);
5769 PlaneClassify(&r_refdef.view.clipplane);
5771 R_ResetViewRendering3D();
5772 R_ClearScreen(r_refdef.fogenabled);
5773 if(r_water_scissormode.integer & 2)
5774 R_View_UpdateWithScissor(myscissor);
5777 if(r_water_scissormode.integer & 1)
5778 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5781 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);
5782 r_waterstate.renderingrefraction = false;
5784 else if (p->materialflags & MATERIALFLAG_CAMERA)
5786 r_refdef.view = myview;
5788 r_refdef.view.clipplane = p->plane;
5789 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5790 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5792 r_refdef.view.width = r_waterstate.camerawidth;
5793 r_refdef.view.height = r_waterstate.cameraheight;
5794 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5795 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5797 if(p->camera_entity)
5799 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5800 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5803 // note: all of the view is used for displaying... so
5804 // there is no use in scissoring
5806 // reverse the cullface settings for this render
5807 r_refdef.view.cullface_front = GL_FRONT;
5808 r_refdef.view.cullface_back = GL_BACK;
5809 // also reverse the view matrix
5810 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
5811 R_RenderView_UpdateViewVectors();
5812 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5814 r_refdef.view.usecustompvs = true;
5815 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);
5818 // camera needs no clipplane
5819 r_refdef.view.useclipplane = false;
5821 PlaneClassify(&r_refdef.view.clipplane);
5823 R_ResetViewRendering3D();
5824 R_ClearScreen(r_refdef.fogenabled);
5828 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);
5829 r_waterstate.renderingrefraction = false;
5833 if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5834 r_waterstate.renderingscene = false;
5835 r_refdef.view = originalview;
5836 R_ResetViewRendering3D();
5837 R_ClearScreen(r_refdef.fogenabled);
5841 r_refdef.view = originalview;
5842 r_waterstate.renderingscene = false;
5843 Cvar_SetValueQuick(&r_water, 0);
5844 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
5846 // lowquality hack, restore cvars
5847 if (qualityreduction > 0)
5849 if (qualityreduction >= 1)
5851 Cvar_SetValueQuick(&r_shadows, old_r_shadows);
5852 Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
5853 Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
5855 if (qualityreduction >= 2)
5857 Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
5858 Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
5859 Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
5864 void R_Bloom_StartFrame(void)
5866 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5867 int viewwidth, viewheight;
5870 if (r_viewscale_fpsscaling.integer)
5872 double actualframetime;
5873 double targetframetime;
5875 actualframetime = r_refdef.lastdrawscreentime;
5876 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5877 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5878 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5879 if (r_viewscale_fpsscaling_stepsize.value > 0)
5880 adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5881 viewscalefpsadjusted += adjust;
5882 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5885 viewscalefpsadjusted = 1.0f;
5887 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5889 switch(vid.renderpath)
5891 case RENDERPATH_GL20:
5892 case RENDERPATH_D3D9:
5893 case RENDERPATH_D3D10:
5894 case RENDERPATH_D3D11:
5895 case RENDERPATH_SOFT:
5896 case RENDERPATH_GLES2:
5898 case RENDERPATH_GL11:
5899 case RENDERPATH_GL13:
5900 case RENDERPATH_GLES1:
5904 // set bloomwidth and bloomheight to the bloom resolution that will be
5905 // used (often less than the screen resolution for faster rendering)
5906 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5907 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5908 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5909 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5910 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5912 // calculate desired texture sizes
5913 if (vid.support.arb_texture_non_power_of_two)
5915 screentexturewidth = vid.width;
5916 screentextureheight = vid.height;
5917 bloomtexturewidth = r_bloomstate.bloomwidth;
5918 bloomtextureheight = r_bloomstate.bloomheight;
5922 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
5923 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
5924 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
5925 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
5928 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))
5930 Cvar_SetValueQuick(&r_hdr, 0);
5931 Cvar_SetValueQuick(&r_bloom, 0);
5932 Cvar_SetValueQuick(&r_motionblur, 0);
5933 Cvar_SetValueQuick(&r_damageblur, 0);
5936 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)
5937 screentexturewidth = screentextureheight = 0;
5938 if (!r_hdr.integer && !r_bloom.integer)
5939 bloomtexturewidth = bloomtextureheight = 0;
5941 textype = TEXTYPE_COLORBUFFER;
5942 switch (vid.renderpath)
5944 case RENDERPATH_GL20:
5945 case RENDERPATH_GLES2:
5946 if (vid.support.ext_framebuffer_object)
5948 if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5949 if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5952 case RENDERPATH_GL11:
5953 case RENDERPATH_GL13:
5954 case RENDERPATH_GLES1:
5955 case RENDERPATH_D3D9:
5956 case RENDERPATH_D3D10:
5957 case RENDERPATH_D3D11:
5958 case RENDERPATH_SOFT:
5962 // allocate textures as needed
5963 if (r_bloomstate.screentexturewidth != screentexturewidth
5964 || r_bloomstate.screentextureheight != screentextureheight
5965 || r_bloomstate.bloomtexturewidth != bloomtexturewidth
5966 || r_bloomstate.bloomtextureheight != bloomtextureheight
5967 || r_bloomstate.texturetype != textype
5968 || r_bloomstate.viewfbo != r_viewfbo.integer)
5970 if (r_bloomstate.texture_bloom)
5971 R_FreeTexture(r_bloomstate.texture_bloom);
5972 r_bloomstate.texture_bloom = NULL;
5973 if (r_bloomstate.texture_screen)
5974 R_FreeTexture(r_bloomstate.texture_screen);
5975 r_bloomstate.texture_screen = NULL;
5976 if (r_bloomstate.fbo_framebuffer)
5977 R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
5978 r_bloomstate.fbo_framebuffer = 0;
5979 if (r_bloomstate.texture_framebuffercolor)
5980 R_FreeTexture(r_bloomstate.texture_framebuffercolor);
5981 r_bloomstate.texture_framebuffercolor = NULL;
5982 if (r_bloomstate.texture_framebufferdepth)
5983 R_FreeTexture(r_bloomstate.texture_framebufferdepth);
5984 r_bloomstate.texture_framebufferdepth = NULL;
5985 r_bloomstate.screentexturewidth = screentexturewidth;
5986 r_bloomstate.screentextureheight = screentextureheight;
5987 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5988 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);
5989 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
5991 // FIXME: choose depth bits based on a cvar
5992 r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
5993 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);
5994 r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5995 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5996 // render depth into one texture and normalmap into the other
6000 qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
6001 qglReadBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
6002 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
6003 if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
6004 Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
6007 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
6008 r_bloomstate.bloomtextureheight = bloomtextureheight;
6009 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
6010 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);
6011 r_bloomstate.viewfbo = r_viewfbo.integer;
6012 r_bloomstate.texturetype = textype;
6015 // when doing a reduced render (HDR) we want to use a smaller area
6016 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
6017 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6018 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
6019 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
6020 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
6022 // set up a texcoord array for the full resolution screen image
6023 // (we have to keep this around to copy back during final render)
6024 r_bloomstate.screentexcoord2f[0] = 0;
6025 r_bloomstate.screentexcoord2f[1] = (float)viewheight / (float)r_bloomstate.screentextureheight;
6026 r_bloomstate.screentexcoord2f[2] = (float)viewwidth / (float)r_bloomstate.screentexturewidth;
6027 r_bloomstate.screentexcoord2f[3] = (float)viewheight / (float)r_bloomstate.screentextureheight;
6028 r_bloomstate.screentexcoord2f[4] = (float)viewwidth / (float)r_bloomstate.screentexturewidth;
6029 r_bloomstate.screentexcoord2f[5] = 0;
6030 r_bloomstate.screentexcoord2f[6] = 0;
6031 r_bloomstate.screentexcoord2f[7] = 0;
6033 // set up a texcoord array for the reduced resolution bloom image
6034 // (which will be additive blended over the screen image)
6035 r_bloomstate.bloomtexcoord2f[0] = 0;
6036 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6037 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6038 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6039 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6040 r_bloomstate.bloomtexcoord2f[5] = 0;
6041 r_bloomstate.bloomtexcoord2f[6] = 0;
6042 r_bloomstate.bloomtexcoord2f[7] = 0;
6044 switch(vid.renderpath)
6046 case RENDERPATH_GL11:
6047 case RENDERPATH_GL13:
6048 case RENDERPATH_GL20:
6049 case RENDERPATH_SOFT:
6050 case RENDERPATH_GLES1:
6051 case RENDERPATH_GLES2:
6053 case RENDERPATH_D3D9:
6054 case RENDERPATH_D3D10:
6055 case RENDERPATH_D3D11:
6058 for (i = 0;i < 4;i++)
6060 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
6061 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
6062 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
6063 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
6069 if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth)
6071 r_bloomstate.enabled = true;
6072 r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer;
6075 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);
6077 if (r_bloomstate.fbo_framebuffer)
6078 r_refdef.view.clear = true;
6081 void R_Bloom_CopyBloomTexture(float colorscale)
6083 r_refdef.stats.bloom++;
6085 // scale down screen texture to the bloom texture size
6087 R_Mesh_SetMainRenderTargets();
6088 R_SetViewport(&r_bloomstate.viewport);
6089 GL_BlendFunc(GL_ONE, GL_ZERO);
6090 GL_Color(colorscale, colorscale, colorscale, 1);
6091 // 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...
6092 switch(vid.renderpath)
6094 case RENDERPATH_GL11:
6095 case RENDERPATH_GL13:
6096 case RENDERPATH_GL20:
6097 case RENDERPATH_GLES1:
6098 case RENDERPATH_GLES2:
6099 case RENDERPATH_SOFT:
6100 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6102 case RENDERPATH_D3D9:
6103 case RENDERPATH_D3D10:
6104 case RENDERPATH_D3D11:
6105 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6108 // TODO: do boxfilter scale-down in shader?
6109 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, true);
6110 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6111 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6113 // we now have a bloom image in the framebuffer
6114 // copy it into the bloom image texture for later processing
6115 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);
6116 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6119 void R_Bloom_CopyHDRTexture(void)
6121 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);
6122 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6125 void R_Bloom_MakeTexture(void)
6128 float xoffset, yoffset, r, brighten;
6130 r_refdef.stats.bloom++;
6132 R_ResetViewRendering2D();
6134 // we have a bloom image in the framebuffer
6136 R_SetViewport(&r_bloomstate.viewport);
6138 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6141 r = bound(0, r_bloom_colorexponent.value / x, 1);
6142 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6144 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
6145 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, true);
6146 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6147 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6149 // copy the vertically blurred bloom view to a texture
6150 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);
6151 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6154 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
6155 brighten = r_bloom_brighten.value;
6156 if (r_bloomstate.hdr)
6157 brighten *= r_hdr_range.value;
6158 brighten = sqrt(brighten);
6160 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6161 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, true);
6163 for (dir = 0;dir < 2;dir++)
6165 // blend on at multiple vertical offsets to achieve a vertical blur
6166 // TODO: do offset blends using GLSL
6167 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6168 GL_BlendFunc(GL_ONE, GL_ZERO);
6169 for (x = -range;x <= range;x++)
6171 if (!dir){xoffset = 0;yoffset = x;}
6172 else {xoffset = x;yoffset = 0;}
6173 xoffset /= (float)r_bloomstate.bloomtexturewidth;
6174 yoffset /= (float)r_bloomstate.bloomtextureheight;
6175 // compute a texcoord array with the specified x and y offset
6176 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
6177 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6178 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6179 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6180 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6181 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
6182 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
6183 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
6184 // this r value looks like a 'dot' particle, fading sharply to
6185 // black at the edges
6186 // (probably not realistic but looks good enough)
6187 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6188 //r = brighten/(range*2+1);
6189 r = brighten / (range * 2 + 1);
6191 r *= (1 - x*x/(float)(range*range));
6192 GL_Color(r, r, r, 1);
6193 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6194 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6195 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6196 GL_BlendFunc(GL_ONE, GL_ONE);
6199 // copy the vertically blurred bloom view to a texture
6200 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);
6201 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6205 void R_HDR_RenderBloomTexture(void)
6207 int oldwidth, oldheight;
6208 float oldcolorscale;
6209 qboolean oldwaterstate;
6211 oldwaterstate = r_waterstate.enabled;
6212 oldcolorscale = r_refdef.view.colorscale;
6213 oldwidth = r_refdef.view.width;
6214 oldheight = r_refdef.view.height;
6215 r_refdef.view.width = r_bloomstate.bloomwidth;
6216 r_refdef.view.height = r_bloomstate.bloomheight;
6218 if(r_hdr.integer < 2)
6219 r_waterstate.enabled = false;
6221 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
6222 // TODO: add exposure compensation features
6223 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6225 r_refdef.view.showdebug = false;
6226 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6228 R_ResetViewRendering3D();
6230 R_ClearScreen(r_refdef.fogenabled);
6231 if (r_timereport_active)
6232 R_TimeReport("HDRclear");
6235 if (r_timereport_active)
6236 R_TimeReport("visibility");
6238 // only do secondary renders with HDR if r_hdr is 2 or higher
6239 r_waterstate.numwaterplanes = 0;
6240 if (r_waterstate.enabled)
6241 R_RenderWaterPlanes();
6243 r_refdef.view.showdebug = true;
6245 r_waterstate.numwaterplanes = 0;
6247 R_ResetViewRendering2D();
6249 R_Bloom_CopyHDRTexture();
6250 R_Bloom_MakeTexture();
6252 // restore the view settings
6253 r_waterstate.enabled = oldwaterstate;
6254 r_refdef.view.width = oldwidth;
6255 r_refdef.view.height = oldheight;
6256 r_refdef.view.colorscale = oldcolorscale;
6258 R_ResetViewRendering3D();
6260 R_ClearScreen(r_refdef.fogenabled);
6261 if (r_timereport_active)
6262 R_TimeReport("viewclear");
6265 static void R_BlendView(void)
6267 unsigned int permutation;
6268 float uservecs[4][4];
6270 switch (vid.renderpath)
6272 case RENDERPATH_GL20:
6273 case RENDERPATH_D3D9:
6274 case RENDERPATH_D3D10:
6275 case RENDERPATH_D3D11:
6276 case RENDERPATH_SOFT:
6277 case RENDERPATH_GLES2:
6279 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6280 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6281 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6282 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6283 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6285 if (r_bloomstate.texture_screen)
6287 // make sure the buffer is available
6288 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6290 R_ResetViewRendering2D();
6291 R_Mesh_SetMainRenderTargets();
6293 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6295 // declare variables
6297 static float avgspeed;
6299 speed = VectorLength(cl.movement_velocity);
6301 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
6302 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
6304 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
6305 speed = bound(0, speed, 1);
6306 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
6308 // calculate values into a standard alpha
6309 cl.motionbluralpha = 1 - exp(-
6311 (r_motionblur.value * speed / 80)
6313 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6316 max(0.0001, cl.time - cl.oldtime) // fps independent
6319 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6320 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6322 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6324 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6325 GL_Color(1, 1, 1, cl.motionbluralpha);
6326 switch(vid.renderpath)
6328 case RENDERPATH_GL11:
6329 case RENDERPATH_GL13:
6330 case RENDERPATH_GL20:
6331 case RENDERPATH_GLES1:
6332 case RENDERPATH_GLES2:
6333 case RENDERPATH_SOFT:
6334 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6336 case RENDERPATH_D3D9:
6337 case RENDERPATH_D3D10:
6338 case RENDERPATH_D3D11:
6339 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6342 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, true);
6343 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6344 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6348 // copy view into the screen texture
6349 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);
6350 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6352 else if (!r_bloomstate.texture_bloom)
6354 // we may still have to do view tint...
6355 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6357 // apply a color tint to the whole view
6358 R_ResetViewRendering2D();
6359 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6360 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6361 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, true);
6362 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6363 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6365 break; // no screen processing, no bloom, skip it
6368 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6370 // render simple bloom effect
6371 // copy the screen and shrink it and darken it for the bloom process
6372 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6373 // make the bloom texture
6374 R_Bloom_MakeTexture();
6377 #if _MSC_VER >= 1400
6378 #define sscanf sscanf_s
6380 memset(uservecs, 0, sizeof(uservecs));
6381 if (r_glsl_postprocess_uservec1_enable.integer)
6382 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6383 if (r_glsl_postprocess_uservec2_enable.integer)
6384 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6385 if (r_glsl_postprocess_uservec3_enable.integer)
6386 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6387 if (r_glsl_postprocess_uservec4_enable.integer)
6388 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6390 R_ResetViewRendering2D();
6391 GL_Color(1, 1, 1, 1);
6392 GL_BlendFunc(GL_ONE, GL_ZERO);
6394 switch(vid.renderpath)
6396 case RENDERPATH_GL20:
6397 case RENDERPATH_GLES2:
6398 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6399 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6400 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_bloomstate.texture_screen);
6401 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_bloomstate.texture_bloom );
6402 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6403 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]);
6404 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6405 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]);
6406 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]);
6407 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]);
6408 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]);
6409 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6410 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6411 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);
6413 case RENDERPATH_D3D9:
6415 // 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...
6416 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6417 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6418 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6419 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6420 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6421 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6422 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6423 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6424 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6425 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6426 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6427 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6428 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6429 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6432 case RENDERPATH_D3D10:
6433 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6435 case RENDERPATH_D3D11:
6436 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6438 case RENDERPATH_SOFT:
6439 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6440 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6441 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6442 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6443 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6444 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6445 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6446 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6447 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6448 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6449 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6450 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6451 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6452 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6457 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6458 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6460 case RENDERPATH_GL11:
6461 case RENDERPATH_GL13:
6462 case RENDERPATH_GLES1:
6463 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6465 // apply a color tint to the whole view
6466 R_ResetViewRendering2D();
6467 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6468 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6469 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, true);
6470 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6471 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6477 matrix4x4_t r_waterscrollmatrix;
6479 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6481 if (r_refdef.fog_density)
6483 r_refdef.fogcolor[0] = r_refdef.fog_red;
6484 r_refdef.fogcolor[1] = r_refdef.fog_green;
6485 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6487 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6488 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6489 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6490 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6494 VectorCopy(r_refdef.fogcolor, fogvec);
6495 // color.rgb *= ContrastBoost * SceneBrightness;
6496 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6497 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6498 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6499 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6504 void R_UpdateVariables(void)
6508 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6510 r_refdef.farclip = r_farclip_base.value;
6511 if (r_refdef.scene.worldmodel)
6512 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6513 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6515 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6516 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6517 r_refdef.polygonfactor = 0;
6518 r_refdef.polygonoffset = 0;
6519 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6520 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6522 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6523 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6524 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6525 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6526 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6527 if (FAKELIGHT_ENABLED)
6529 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6531 if (r_showsurfaces.integer)
6533 r_refdef.scene.rtworld = false;
6534 r_refdef.scene.rtworldshadows = false;
6535 r_refdef.scene.rtdlight = false;
6536 r_refdef.scene.rtdlightshadows = false;
6537 r_refdef.lightmapintensity = 0;
6540 if (gamemode == GAME_NEHAHRA)
6542 if (gl_fogenable.integer)
6544 r_refdef.oldgl_fogenable = true;
6545 r_refdef.fog_density = gl_fogdensity.value;
6546 r_refdef.fog_red = gl_fogred.value;
6547 r_refdef.fog_green = gl_foggreen.value;
6548 r_refdef.fog_blue = gl_fogblue.value;
6549 r_refdef.fog_alpha = 1;
6550 r_refdef.fog_start = 0;
6551 r_refdef.fog_end = gl_skyclip.value;
6552 r_refdef.fog_height = 1<<30;
6553 r_refdef.fog_fadedepth = 128;
6555 else if (r_refdef.oldgl_fogenable)
6557 r_refdef.oldgl_fogenable = false;
6558 r_refdef.fog_density = 0;
6559 r_refdef.fog_red = 0;
6560 r_refdef.fog_green = 0;
6561 r_refdef.fog_blue = 0;
6562 r_refdef.fog_alpha = 0;
6563 r_refdef.fog_start = 0;
6564 r_refdef.fog_end = 0;
6565 r_refdef.fog_height = 1<<30;
6566 r_refdef.fog_fadedepth = 128;
6570 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6571 r_refdef.fog_start = max(0, r_refdef.fog_start);
6572 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6574 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6576 if (r_refdef.fog_density && r_drawfog.integer)
6578 r_refdef.fogenabled = true;
6579 // this is the point where the fog reaches 0.9986 alpha, which we
6580 // consider a good enough cutoff point for the texture
6581 // (0.9986 * 256 == 255.6)
6582 if (r_fog_exp2.integer)
6583 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6585 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6586 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6587 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6588 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6589 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6590 R_BuildFogHeightTexture();
6591 // fog color was already set
6592 // update the fog texture
6593 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)
6594 R_BuildFogTexture();
6595 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6596 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6599 r_refdef.fogenabled = false;
6601 switch(vid.renderpath)
6603 case RENDERPATH_GL20:
6604 case RENDERPATH_D3D9:
6605 case RENDERPATH_D3D10:
6606 case RENDERPATH_D3D11:
6607 case RENDERPATH_SOFT:
6608 case RENDERPATH_GLES2:
6609 if(v_glslgamma.integer && !vid_gammatables_trivial)
6611 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6613 // build GLSL gamma texture
6614 #define RAMPWIDTH 256
6615 unsigned short ramp[RAMPWIDTH * 3];
6616 unsigned char rampbgr[RAMPWIDTH][4];
6619 r_texture_gammaramps_serial = vid_gammatables_serial;
6621 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6622 for(i = 0; i < RAMPWIDTH; ++i)
6624 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6625 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6626 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6629 if (r_texture_gammaramps)
6631 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6635 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6641 // remove GLSL gamma texture
6644 case RENDERPATH_GL11:
6645 case RENDERPATH_GL13:
6646 case RENDERPATH_GLES1:
6651 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6652 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6658 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6659 if( scenetype != r_currentscenetype ) {
6660 // store the old scenetype
6661 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6662 r_currentscenetype = scenetype;
6663 // move in the new scene
6664 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6673 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6675 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6676 if( scenetype == r_currentscenetype ) {
6677 return &r_refdef.scene;
6679 return &r_scenes_store[ scenetype ];
6688 int dpsoftrast_test;
6689 void R_RenderView(void)
6691 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6693 dpsoftrast_test = r_test.integer;
6695 if (r_timereport_active)
6696 R_TimeReport("start");
6697 r_textureframe++; // used only by R_GetCurrentTexture
6698 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6700 if(R_CompileShader_CheckStaticParms())
6703 if (!r_drawentities.integer)
6704 r_refdef.scene.numentities = 0;
6706 R_AnimCache_ClearCache();
6707 R_FrameData_NewFrame();
6709 /* adjust for stereo display */
6710 if(R_Stereo_Active())
6712 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);
6713 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6716 if (r_refdef.view.isoverlay)
6718 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6719 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6720 R_TimeReport("depthclear");
6722 r_refdef.view.showdebug = false;
6724 r_waterstate.enabled = false;
6725 r_waterstate.numwaterplanes = 0;
6729 r_refdef.view.matrix = originalmatrix;
6735 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6737 r_refdef.view.matrix = originalmatrix;
6738 return; //Host_Error ("R_RenderView: NULL worldmodel");
6741 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6743 R_RenderView_UpdateViewVectors();
6745 R_Shadow_UpdateWorldLightSelection();
6747 R_Bloom_StartFrame();
6748 R_Water_StartFrame();
6751 if (r_timereport_active)
6752 R_TimeReport("viewsetup");
6754 R_ResetViewRendering3D();
6756 if (r_refdef.view.clear || r_refdef.fogenabled)
6758 R_ClearScreen(r_refdef.fogenabled);
6759 if (r_timereport_active)
6760 R_TimeReport("viewclear");
6762 r_refdef.view.clear = true;
6764 // this produces a bloom texture to be used in R_BlendView() later
6765 if (r_bloomstate.hdr)
6767 R_HDR_RenderBloomTexture();
6768 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6769 r_textureframe++; // used only by R_GetCurrentTexture
6772 r_refdef.view.showdebug = true;
6775 if (r_timereport_active)
6776 R_TimeReport("visibility");
6778 r_waterstate.numwaterplanes = 0;
6779 if (r_waterstate.enabled)
6780 R_RenderWaterPlanes();
6783 r_waterstate.numwaterplanes = 0;
6786 if (r_timereport_active)
6787 R_TimeReport("blendview");
6789 GL_Scissor(0, 0, vid.width, vid.height);
6790 GL_ScissorTest(false);
6792 r_refdef.view.matrix = originalmatrix;
6797 void R_RenderWaterPlanes(void)
6799 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6801 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6802 if (r_timereport_active)
6803 R_TimeReport("waterworld");
6806 // don't let sound skip if going slow
6807 if (r_refdef.scene.extraupdate)
6810 R_DrawModelsAddWaterPlanes();
6811 if (r_timereport_active)
6812 R_TimeReport("watermodels");
6814 if (r_waterstate.numwaterplanes)
6816 R_Water_ProcessPlanes();
6817 if (r_timereport_active)
6818 R_TimeReport("waterscenes");
6822 extern void R_DrawLightningBeams (void);
6823 extern void VM_CL_AddPolygonsToMeshQueue (void);
6824 extern void R_DrawPortals (void);
6825 extern cvar_t cl_locs_show;
6826 static void R_DrawLocs(void);
6827 static void R_DrawEntityBBoxes(void);
6828 static void R_DrawModelDecals(void);
6829 extern void R_DrawModelShadows(void);
6830 extern void R_DrawModelShadowMaps(void);
6831 extern cvar_t cl_decals_newsystem;
6832 extern qboolean r_shadow_usingdeferredprepass;
6833 void R_RenderScene(void)
6835 qboolean shadowmapping = false;
6837 if (r_timereport_active)
6838 R_TimeReport("beginscene");
6840 r_refdef.stats.renders++;
6844 // don't let sound skip if going slow
6845 if (r_refdef.scene.extraupdate)
6848 R_MeshQueue_BeginScene();
6852 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);
6854 if (r_timereport_active)
6855 R_TimeReport("skystartframe");
6857 if (cl.csqc_vidvars.drawworld)
6859 // don't let sound skip if going slow
6860 if (r_refdef.scene.extraupdate)
6863 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6865 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6866 if (r_timereport_active)
6867 R_TimeReport("worldsky");
6870 if (R_DrawBrushModelsSky() && r_timereport_active)
6871 R_TimeReport("bmodelsky");
6873 if (skyrendermasked && skyrenderlater)
6875 // we have to force off the water clipping plane while rendering sky
6879 if (r_timereport_active)
6880 R_TimeReport("sky");
6884 R_AnimCache_CacheVisibleEntities();
6885 if (r_timereport_active)
6886 R_TimeReport("animation");
6888 R_Shadow_PrepareLights();
6889 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6890 R_Shadow_PrepareModelShadows();
6891 if (r_timereport_active)
6892 R_TimeReport("preparelights");
6894 if (R_Shadow_ShadowMappingEnabled())
6895 shadowmapping = true;
6897 if (r_shadow_usingdeferredprepass)
6898 R_Shadow_DrawPrepass();
6900 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6902 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6903 if (r_timereport_active)
6904 R_TimeReport("worlddepth");
6906 if (r_depthfirst.integer >= 2)
6908 R_DrawModelsDepth();
6909 if (r_timereport_active)
6910 R_TimeReport("modeldepth");
6913 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6915 R_DrawModelShadowMaps();
6916 R_ResetViewRendering3D();
6917 // don't let sound skip if going slow
6918 if (r_refdef.scene.extraupdate)
6922 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6924 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6925 if (r_timereport_active)
6926 R_TimeReport("world");
6929 // don't let sound skip if going slow
6930 if (r_refdef.scene.extraupdate)
6934 if (r_timereport_active)
6935 R_TimeReport("models");
6937 // don't let sound skip if going slow
6938 if (r_refdef.scene.extraupdate)
6941 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6943 R_DrawModelShadows();
6944 R_ResetViewRendering3D();
6945 // don't let sound skip if going slow
6946 if (r_refdef.scene.extraupdate)
6950 if (!r_shadow_usingdeferredprepass)
6952 R_Shadow_DrawLights();
6953 if (r_timereport_active)
6954 R_TimeReport("rtlights");
6957 // don't let sound skip if going slow
6958 if (r_refdef.scene.extraupdate)
6961 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6963 R_DrawModelShadows();
6964 R_ResetViewRendering3D();
6965 // don't let sound skip if going slow
6966 if (r_refdef.scene.extraupdate)
6970 if (cl.csqc_vidvars.drawworld)
6972 if (cl_decals_newsystem.integer)
6974 R_DrawModelDecals();
6975 if (r_timereport_active)
6976 R_TimeReport("modeldecals");
6981 if (r_timereport_active)
6982 R_TimeReport("decals");
6986 if (r_timereport_active)
6987 R_TimeReport("particles");
6990 if (r_timereport_active)
6991 R_TimeReport("explosions");
6993 R_DrawLightningBeams();
6994 if (r_timereport_active)
6995 R_TimeReport("lightning");
6998 VM_CL_AddPolygonsToMeshQueue();
7000 if (r_refdef.view.showdebug)
7002 if (cl_locs_show.integer)
7005 if (r_timereport_active)
7006 R_TimeReport("showlocs");
7009 if (r_drawportals.integer)
7012 if (r_timereport_active)
7013 R_TimeReport("portals");
7016 if (r_showbboxes.value > 0)
7018 R_DrawEntityBBoxes();
7019 if (r_timereport_active)
7020 R_TimeReport("bboxes");
7024 if (r_transparent.integer)
7026 R_MeshQueue_RenderTransparent();
7027 if (r_timereport_active)
7028 R_TimeReport("drawtrans");
7031 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))
7033 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7034 if (r_timereport_active)
7035 R_TimeReport("worlddebug");
7036 R_DrawModelsDebug();
7037 if (r_timereport_active)
7038 R_TimeReport("modeldebug");
7041 if (cl.csqc_vidvars.drawworld)
7043 R_Shadow_DrawCoronas();
7044 if (r_timereport_active)
7045 R_TimeReport("coronas");
7050 GL_DepthTest(false);
7051 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7052 GL_Color(1, 1, 1, 1);
7053 qglBegin(GL_POLYGON);
7054 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7055 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7056 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7057 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7059 qglBegin(GL_POLYGON);
7060 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]);
7061 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]);
7062 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]);
7063 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]);
7065 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7069 // don't let sound skip if going slow
7070 if (r_refdef.scene.extraupdate)
7073 R_ResetViewRendering2D();
7076 static const unsigned short bboxelements[36] =
7086 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7089 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7091 RSurf_ActiveWorldEntity();
7093 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7094 GL_DepthMask(false);
7095 GL_DepthRange(0, 1);
7096 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7097 // R_Mesh_ResetTextureState();
7099 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7100 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7101 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7102 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7103 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7104 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7105 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7106 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7107 R_FillColors(color4f, 8, cr, cg, cb, ca);
7108 if (r_refdef.fogenabled)
7110 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7112 f1 = RSurf_FogVertex(v);
7114 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7115 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7116 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7119 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7120 R_Mesh_ResetTextureState();
7121 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
7122 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7125 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7129 prvm_edict_t *edict;
7130 prvm_prog_t *prog_save = prog;
7132 // this function draws bounding boxes of server entities
7136 GL_CullFace(GL_NONE);
7137 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
7141 for (i = 0;i < numsurfaces;i++)
7143 edict = PRVM_EDICT_NUM(surfacelist[i]);
7144 switch ((int)PRVM_serveredictfloat(edict, solid))
7146 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
7147 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
7148 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
7149 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7150 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
7151 default: Vector4Set(color, 0, 0, 0, 0.50);break;
7153 color[3] *= r_showbboxes.value;
7154 color[3] = bound(0, color[3], 1);
7155 GL_DepthTest(!r_showdisabledepthtest.integer);
7156 GL_CullFace(r_refdef.view.cullface_front);
7157 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7163 static void R_DrawEntityBBoxes(void)
7166 prvm_edict_t *edict;
7168 prvm_prog_t *prog_save = prog;
7170 // this function draws bounding boxes of server entities
7176 for (i = 0;i < prog->num_edicts;i++)
7178 edict = PRVM_EDICT_NUM(i);
7179 if (edict->priv.server->free)
7181 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7182 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7184 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7186 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7187 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7193 static const int nomodelelement3i[24] =
7205 static const unsigned short nomodelelement3s[24] =
7217 static const float nomodelvertex3f[6*3] =
7227 static const float nomodelcolor4f[6*4] =
7229 0.0f, 0.0f, 0.5f, 1.0f,
7230 0.0f, 0.0f, 0.5f, 1.0f,
7231 0.0f, 0.5f, 0.0f, 1.0f,
7232 0.0f, 0.5f, 0.0f, 1.0f,
7233 0.5f, 0.0f, 0.0f, 1.0f,
7234 0.5f, 0.0f, 0.0f, 1.0f
7237 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7243 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);
7245 // this is only called once per entity so numsurfaces is always 1, and
7246 // surfacelist is always {0}, so this code does not handle batches
7248 if (rsurface.ent_flags & RENDER_ADDITIVE)
7250 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7251 GL_DepthMask(false);
7253 else if (rsurface.colormod[3] < 1)
7255 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7256 GL_DepthMask(false);
7260 GL_BlendFunc(GL_ONE, GL_ZERO);
7263 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7264 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7265 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7266 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7267 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7268 for (i = 0, c = color4f;i < 6;i++, c += 4)
7270 c[0] *= rsurface.colormod[0];
7271 c[1] *= rsurface.colormod[1];
7272 c[2] *= rsurface.colormod[2];
7273 c[3] *= rsurface.colormod[3];
7275 if (r_refdef.fogenabled)
7277 for (i = 0, c = color4f;i < 6;i++, c += 4)
7279 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7281 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7282 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7283 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7286 // R_Mesh_ResetTextureState();
7287 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
7288 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7289 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7292 void R_DrawNoModel(entity_render_t *ent)
7295 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7296 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7297 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7299 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7302 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7304 vec3_t right1, right2, diff, normal;
7306 VectorSubtract (org2, org1, normal);
7308 // calculate 'right' vector for start
7309 VectorSubtract (r_refdef.view.origin, org1, diff);
7310 CrossProduct (normal, diff, right1);
7311 VectorNormalize (right1);
7313 // calculate 'right' vector for end
7314 VectorSubtract (r_refdef.view.origin, org2, diff);
7315 CrossProduct (normal, diff, right2);
7316 VectorNormalize (right2);
7318 vert[ 0] = org1[0] + width * right1[0];
7319 vert[ 1] = org1[1] + width * right1[1];
7320 vert[ 2] = org1[2] + width * right1[2];
7321 vert[ 3] = org1[0] - width * right1[0];
7322 vert[ 4] = org1[1] - width * right1[1];
7323 vert[ 5] = org1[2] - width * right1[2];
7324 vert[ 6] = org2[0] - width * right2[0];
7325 vert[ 7] = org2[1] - width * right2[1];
7326 vert[ 8] = org2[2] - width * right2[2];
7327 vert[ 9] = org2[0] + width * right2[0];
7328 vert[10] = org2[1] + width * right2[1];
7329 vert[11] = org2[2] + width * right2[2];
7332 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)
7334 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7335 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7336 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7337 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7338 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7339 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7340 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7341 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7342 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7343 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7344 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7345 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7348 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7353 VectorSet(v, x, y, z);
7354 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7355 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7357 if (i == mesh->numvertices)
7359 if (mesh->numvertices < mesh->maxvertices)
7361 VectorCopy(v, vertex3f);
7362 mesh->numvertices++;
7364 return mesh->numvertices;
7370 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7374 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7375 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7376 e = mesh->element3i + mesh->numtriangles * 3;
7377 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7379 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7380 if (mesh->numtriangles < mesh->maxtriangles)
7385 mesh->numtriangles++;
7387 element[1] = element[2];
7391 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7395 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7396 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7397 e = mesh->element3i + mesh->numtriangles * 3;
7398 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7400 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7401 if (mesh->numtriangles < mesh->maxtriangles)
7406 mesh->numtriangles++;
7408 element[1] = element[2];
7412 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7413 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7415 int planenum, planenum2;
7418 mplane_t *plane, *plane2;
7420 double temppoints[2][256*3];
7421 // figure out how large a bounding box we need to properly compute this brush
7423 for (w = 0;w < numplanes;w++)
7424 maxdist = max(maxdist, fabs(planes[w].dist));
7425 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7426 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7427 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7431 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7432 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7434 if (planenum2 == planenum)
7436 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);
7439 if (tempnumpoints < 3)
7441 // generate elements forming a triangle fan for this polygon
7442 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7446 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)
7448 texturelayer_t *layer;
7449 layer = t->currentlayers + t->currentnumlayers++;
7451 layer->depthmask = depthmask;
7452 layer->blendfunc1 = blendfunc1;
7453 layer->blendfunc2 = blendfunc2;
7454 layer->texture = texture;
7455 layer->texmatrix = *matrix;
7456 layer->color[0] = r;
7457 layer->color[1] = g;
7458 layer->color[2] = b;
7459 layer->color[3] = a;
7462 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7464 if(parms[0] == 0 && parms[1] == 0)
7466 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7467 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7472 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7475 index = parms[2] + rsurface.shadertime * parms[3];
7476 index -= floor(index);
7477 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7480 case Q3WAVEFUNC_NONE:
7481 case Q3WAVEFUNC_NOISE:
7482 case Q3WAVEFUNC_COUNT:
7485 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7486 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7487 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7488 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7489 case Q3WAVEFUNC_TRIANGLE:
7491 f = index - floor(index);
7502 f = parms[0] + parms[1] * f;
7503 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7504 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7508 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7514 matrix4x4_t matrix, temp;
7515 switch(tcmod->tcmod)
7519 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7520 matrix = r_waterscrollmatrix;
7522 matrix = identitymatrix;
7524 case Q3TCMOD_ENTITYTRANSLATE:
7525 // this is used in Q3 to allow the gamecode to control texcoord
7526 // scrolling on the entity, which is not supported in darkplaces yet.
7527 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7529 case Q3TCMOD_ROTATE:
7530 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7531 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
7532 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7535 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7537 case Q3TCMOD_SCROLL:
7538 // extra care is needed because of precision breakdown with large values of time
7539 offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7540 offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7541 Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7543 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7544 w = (int) tcmod->parms[0];
7545 h = (int) tcmod->parms[1];
7546 f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7548 idx = (int) floor(f * w * h);
7549 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7551 case Q3TCMOD_STRETCH:
7552 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7553 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7555 case Q3TCMOD_TRANSFORM:
7556 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
7557 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
7558 VectorSet(tcmat + 6, 0 , 0 , 1);
7559 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
7560 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7562 case Q3TCMOD_TURBULENT:
7563 // this is handled in the RSurf_PrepareVertices function
7564 matrix = identitymatrix;
7568 Matrix4x4_Concat(texmatrix, &matrix, &temp);
7571 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7573 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7574 char name[MAX_QPATH];
7575 skinframe_t *skinframe;
7576 unsigned char pixels[296*194];
7577 strlcpy(cache->name, skinname, sizeof(cache->name));
7578 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7579 if (developer_loading.integer)
7580 Con_Printf("loading %s\n", name);
7581 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7582 if (!skinframe || !skinframe->base)
7585 fs_offset_t filesize;
7587 f = FS_LoadFile(name, tempmempool, true, &filesize);
7590 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7591 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7595 cache->skinframe = skinframe;
7598 texture_t *R_GetCurrentTexture(texture_t *t)
7601 const entity_render_t *ent = rsurface.entity;
7602 dp_model_t *model = ent->model;
7603 q3shaderinfo_layer_tcmod_t *tcmod;
7605 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7606 return t->currentframe;
7607 t->update_lastrenderframe = r_textureframe;
7608 t->update_lastrenderentity = (void *)ent;
7610 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7611 t->camera_entity = ent->entitynumber;
7613 t->camera_entity = 0;
7615 // switch to an alternate material if this is a q1bsp animated material
7617 texture_t *texture = t;
7618 int s = rsurface.ent_skinnum;
7619 if ((unsigned int)s >= (unsigned int)model->numskins)
7621 if (model->skinscenes)
7623 if (model->skinscenes[s].framecount > 1)
7624 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7626 s = model->skinscenes[s].firstframe;
7629 t = t + s * model->num_surfaces;
7632 // use an alternate animation if the entity's frame is not 0,
7633 // and only if the texture has an alternate animation
7634 if (rsurface.ent_alttextures && t->anim_total[1])
7635 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7637 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7639 texture->currentframe = t;
7642 // update currentskinframe to be a qw skin or animation frame
7643 if (rsurface.ent_qwskin >= 0)
7645 i = rsurface.ent_qwskin;
7646 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7648 r_qwskincache_size = cl.maxclients;
7650 Mem_Free(r_qwskincache);
7651 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7653 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7654 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7655 t->currentskinframe = r_qwskincache[i].skinframe;
7656 if (t->currentskinframe == NULL)
7657 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7659 else if (t->numskinframes >= 2)
7660 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7661 if (t->backgroundnumskinframes >= 2)
7662 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7664 t->currentmaterialflags = t->basematerialflags;
7665 t->currentalpha = rsurface.colormod[3];
7666 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7667 t->currentalpha *= r_wateralpha.value;
7668 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7669 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7670 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7671 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7672 if (!(rsurface.ent_flags & RENDER_LIGHT))
7673 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7674 else if (FAKELIGHT_ENABLED)
7676 // no modellight if using fakelight for the map
7678 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7680 // pick a model lighting mode
7681 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7682 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7684 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7686 if (rsurface.ent_flags & RENDER_ADDITIVE)
7687 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7688 else if (t->currentalpha < 1)
7689 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7690 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7691 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7692 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7693 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7694 if (t->backgroundnumskinframes)
7695 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7696 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7698 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7699 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7702 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7703 if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
7705 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
7706 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
7708 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7709 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7711 // there is no tcmod
7712 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7714 t->currenttexmatrix = r_waterscrollmatrix;
7715 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7717 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7719 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7720 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7723 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7724 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7725 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7726 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7728 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7729 if (t->currentskinframe->qpixels)
7730 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7731 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7732 if (!t->basetexture)
7733 t->basetexture = r_texture_notexture;
7734 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7735 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7736 t->nmaptexture = t->currentskinframe->nmap;
7737 if (!t->nmaptexture)
7738 t->nmaptexture = r_texture_blanknormalmap;
7739 t->glosstexture = r_texture_black;
7740 t->glowtexture = t->currentskinframe->glow;
7741 t->fogtexture = t->currentskinframe->fog;
7742 t->reflectmasktexture = t->currentskinframe->reflect;
7743 if (t->backgroundnumskinframes)
7745 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7746 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7747 t->backgroundglosstexture = r_texture_black;
7748 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7749 if (!t->backgroundnmaptexture)
7750 t->backgroundnmaptexture = r_texture_blanknormalmap;
7754 t->backgroundbasetexture = r_texture_white;
7755 t->backgroundnmaptexture = r_texture_blanknormalmap;
7756 t->backgroundglosstexture = r_texture_black;
7757 t->backgroundglowtexture = NULL;
7759 t->specularpower = r_shadow_glossexponent.value;
7760 // TODO: store reference values for these in the texture?
7761 t->specularscale = 0;
7762 if (r_shadow_gloss.integer > 0)
7764 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7766 if (r_shadow_glossintensity.value > 0)
7768 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7769 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7770 t->specularscale = r_shadow_glossintensity.value;
7773 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7775 t->glosstexture = r_texture_white;
7776 t->backgroundglosstexture = r_texture_white;
7777 t->specularscale = r_shadow_gloss2intensity.value;
7778 t->specularpower = r_shadow_gloss2exponent.value;
7781 t->specularscale *= t->specularscalemod;
7782 t->specularpower *= t->specularpowermod;
7784 // lightmaps mode looks bad with dlights using actual texturing, so turn
7785 // off the colormap and glossmap, but leave the normalmap on as it still
7786 // accurately represents the shading involved
7787 if (gl_lightmaps.integer)
7789 t->basetexture = r_texture_grey128;
7790 t->pantstexture = r_texture_black;
7791 t->shirttexture = r_texture_black;
7792 t->nmaptexture = r_texture_blanknormalmap;
7793 t->glosstexture = r_texture_black;
7794 t->glowtexture = NULL;
7795 t->fogtexture = NULL;
7796 t->reflectmasktexture = NULL;
7797 t->backgroundbasetexture = NULL;
7798 t->backgroundnmaptexture = r_texture_blanknormalmap;
7799 t->backgroundglosstexture = r_texture_black;
7800 t->backgroundglowtexture = NULL;
7801 t->specularscale = 0;
7802 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7805 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7806 VectorClear(t->dlightcolor);
7807 t->currentnumlayers = 0;
7808 if (t->currentmaterialflags & MATERIALFLAG_WALL)
7810 int blendfunc1, blendfunc2;
7812 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7814 blendfunc1 = GL_SRC_ALPHA;
7815 blendfunc2 = GL_ONE;
7817 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7819 blendfunc1 = GL_SRC_ALPHA;
7820 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7822 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7824 blendfunc1 = t->customblendfunc[0];
7825 blendfunc2 = t->customblendfunc[1];
7829 blendfunc1 = GL_ONE;
7830 blendfunc2 = GL_ZERO;
7832 // don't colormod evilblend textures
7833 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7834 VectorSet(t->lightmapcolor, 1, 1, 1);
7835 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7836 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7838 // fullbright is not affected by r_refdef.lightmapintensity
7839 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]);
7840 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7841 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]);
7842 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7843 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]);
7847 vec3_t ambientcolor;
7849 // set the color tint used for lights affecting this surface
7850 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7852 // q3bsp has no lightmap updates, so the lightstylevalue that
7853 // would normally be baked into the lightmap must be
7854 // applied to the color
7855 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7856 if (model->type == mod_brushq3)
7857 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7858 colorscale *= r_refdef.lightmapintensity;
7859 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7860 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7861 // basic lit geometry
7862 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]);
7863 // add pants/shirt if needed
7864 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7865 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]);
7866 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7867 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]);
7868 // now add ambient passes if needed
7869 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7871 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]);
7872 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7873 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]);
7874 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7875 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]);
7878 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7879 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]);
7880 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7882 // if this is opaque use alpha blend which will darken the earlier
7885 // if this is an alpha blended material, all the earlier passes
7886 // were darkened by fog already, so we only need to add the fog
7887 // color ontop through the fog mask texture
7889 // if this is an additive blended material, all the earlier passes
7890 // were darkened by fog already, and we should not add fog color
7891 // (because the background was not darkened, there is no fog color
7892 // that was lost behind it).
7893 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]);
7897 return t->currentframe;
7900 rsurfacestate_t rsurface;
7902 void RSurf_ActiveWorldEntity(void)
7904 dp_model_t *model = r_refdef.scene.worldmodel;
7905 //if (rsurface.entity == r_refdef.scene.worldentity)
7907 rsurface.entity = r_refdef.scene.worldentity;
7908 rsurface.skeleton = NULL;
7909 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7910 rsurface.ent_skinnum = 0;
7911 rsurface.ent_qwskin = -1;
7912 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7913 rsurface.shadertime = r_refdef.scene.time;
7914 rsurface.matrix = identitymatrix;
7915 rsurface.inversematrix = identitymatrix;
7916 rsurface.matrixscale = 1;
7917 rsurface.inversematrixscale = 1;
7918 R_EntityMatrix(&identitymatrix);
7919 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7920 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7921 rsurface.fograngerecip = r_refdef.fograngerecip;
7922 rsurface.fogheightfade = r_refdef.fogheightfade;
7923 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7924 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7925 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7926 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7927 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7928 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7929 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7930 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7931 rsurface.colormod[3] = 1;
7932 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);
7933 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7934 rsurface.frameblend[0].lerp = 1;
7935 rsurface.ent_alttextures = false;
7936 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7937 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7938 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7939 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7940 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7941 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7942 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7943 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7944 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7945 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7946 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7947 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7948 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7949 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7950 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7951 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7952 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7953 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7954 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7955 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7956 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7957 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7958 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7959 rsurface.modelelement3i = model->surfmesh.data_element3i;
7960 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7961 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7962 rsurface.modelelement3s = model->surfmesh.data_element3s;
7963 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7964 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7965 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7966 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7967 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7968 rsurface.modelsurfaces = model->data_surfaces;
7969 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7970 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7971 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7972 rsurface.modelgeneratedvertex = false;
7973 rsurface.batchgeneratedvertex = false;
7974 rsurface.batchfirstvertex = 0;
7975 rsurface.batchnumvertices = 0;
7976 rsurface.batchfirsttriangle = 0;
7977 rsurface.batchnumtriangles = 0;
7978 rsurface.batchvertex3f = NULL;
7979 rsurface.batchvertex3f_vertexbuffer = NULL;
7980 rsurface.batchvertex3f_bufferoffset = 0;
7981 rsurface.batchsvector3f = NULL;
7982 rsurface.batchsvector3f_vertexbuffer = NULL;
7983 rsurface.batchsvector3f_bufferoffset = 0;
7984 rsurface.batchtvector3f = NULL;
7985 rsurface.batchtvector3f_vertexbuffer = NULL;
7986 rsurface.batchtvector3f_bufferoffset = 0;
7987 rsurface.batchnormal3f = NULL;
7988 rsurface.batchnormal3f_vertexbuffer = NULL;
7989 rsurface.batchnormal3f_bufferoffset = 0;
7990 rsurface.batchlightmapcolor4f = NULL;
7991 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7992 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7993 rsurface.batchtexcoordtexture2f = NULL;
7994 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7995 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7996 rsurface.batchtexcoordlightmap2f = NULL;
7997 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7998 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7999 rsurface.batchvertexmesh = NULL;
8000 rsurface.batchvertexmeshbuffer = NULL;
8001 rsurface.batchvertex3fbuffer = NULL;
8002 rsurface.batchelement3i = NULL;
8003 rsurface.batchelement3i_indexbuffer = NULL;
8004 rsurface.batchelement3i_bufferoffset = 0;
8005 rsurface.batchelement3s = NULL;
8006 rsurface.batchelement3s_indexbuffer = NULL;
8007 rsurface.batchelement3s_bufferoffset = 0;
8008 rsurface.passcolor4f = NULL;
8009 rsurface.passcolor4f_vertexbuffer = NULL;
8010 rsurface.passcolor4f_bufferoffset = 0;
8013 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8015 dp_model_t *model = ent->model;
8016 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8018 rsurface.entity = (entity_render_t *)ent;
8019 rsurface.skeleton = ent->skeleton;
8020 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8021 rsurface.ent_skinnum = ent->skinnum;
8022 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;
8023 rsurface.ent_flags = ent->flags;
8024 rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8025 rsurface.matrix = ent->matrix;
8026 rsurface.inversematrix = ent->inversematrix;
8027 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8028 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8029 R_EntityMatrix(&rsurface.matrix);
8030 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8031 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8032 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8033 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8034 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8035 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8036 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8037 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8038 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8039 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8040 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8041 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8042 rsurface.colormod[3] = ent->alpha;
8043 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8044 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8045 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8046 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8047 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8048 if (ent->model->brush.submodel && !prepass)
8050 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8051 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8053 if (model->surfmesh.isanimated && model->AnimateVertices)
8055 if (ent->animcache_vertex3f)
8057 rsurface.modelvertex3f = ent->animcache_vertex3f;
8058 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8059 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8060 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8061 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8062 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8063 rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8065 else if (wanttangents)
8067 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8068 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8069 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8070 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8071 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8072 rsurface.modelvertexmesh = NULL;
8073 rsurface.modelvertexmeshbuffer = NULL;
8074 rsurface.modelvertex3fbuffer = NULL;
8076 else if (wantnormals)
8078 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8079 rsurface.modelsvector3f = NULL;
8080 rsurface.modeltvector3f = NULL;
8081 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8082 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8083 rsurface.modelvertexmesh = NULL;
8084 rsurface.modelvertexmeshbuffer = NULL;
8085 rsurface.modelvertex3fbuffer = NULL;
8089 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8090 rsurface.modelsvector3f = NULL;
8091 rsurface.modeltvector3f = NULL;
8092 rsurface.modelnormal3f = NULL;
8093 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8094 rsurface.modelvertexmesh = NULL;
8095 rsurface.modelvertexmeshbuffer = NULL;
8096 rsurface.modelvertex3fbuffer = NULL;
8098 rsurface.modelvertex3f_vertexbuffer = 0;
8099 rsurface.modelvertex3f_bufferoffset = 0;
8100 rsurface.modelsvector3f_vertexbuffer = 0;
8101 rsurface.modelsvector3f_bufferoffset = 0;
8102 rsurface.modeltvector3f_vertexbuffer = 0;
8103 rsurface.modeltvector3f_bufferoffset = 0;
8104 rsurface.modelnormal3f_vertexbuffer = 0;
8105 rsurface.modelnormal3f_bufferoffset = 0;
8106 rsurface.modelgeneratedvertex = true;
8110 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8111 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8112 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8113 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8114 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8115 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8116 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8117 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8118 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8119 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8120 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8121 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8122 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8123 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8124 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8125 rsurface.modelgeneratedvertex = false;
8127 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8128 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8129 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8130 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8131 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8132 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8133 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8134 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8135 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8136 rsurface.modelelement3i = model->surfmesh.data_element3i;
8137 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8138 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8139 rsurface.modelelement3s = model->surfmesh.data_element3s;
8140 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8141 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8142 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8143 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8144 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8145 rsurface.modelsurfaces = model->data_surfaces;
8146 rsurface.batchgeneratedvertex = false;
8147 rsurface.batchfirstvertex = 0;
8148 rsurface.batchnumvertices = 0;
8149 rsurface.batchfirsttriangle = 0;
8150 rsurface.batchnumtriangles = 0;
8151 rsurface.batchvertex3f = NULL;
8152 rsurface.batchvertex3f_vertexbuffer = NULL;
8153 rsurface.batchvertex3f_bufferoffset = 0;
8154 rsurface.batchsvector3f = NULL;
8155 rsurface.batchsvector3f_vertexbuffer = NULL;
8156 rsurface.batchsvector3f_bufferoffset = 0;
8157 rsurface.batchtvector3f = NULL;
8158 rsurface.batchtvector3f_vertexbuffer = NULL;
8159 rsurface.batchtvector3f_bufferoffset = 0;
8160 rsurface.batchnormal3f = NULL;
8161 rsurface.batchnormal3f_vertexbuffer = NULL;
8162 rsurface.batchnormal3f_bufferoffset = 0;
8163 rsurface.batchlightmapcolor4f = NULL;
8164 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8165 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8166 rsurface.batchtexcoordtexture2f = NULL;
8167 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8168 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8169 rsurface.batchtexcoordlightmap2f = NULL;
8170 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8171 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8172 rsurface.batchvertexmesh = NULL;
8173 rsurface.batchvertexmeshbuffer = NULL;
8174 rsurface.batchvertex3fbuffer = NULL;
8175 rsurface.batchelement3i = NULL;
8176 rsurface.batchelement3i_indexbuffer = NULL;
8177 rsurface.batchelement3i_bufferoffset = 0;
8178 rsurface.batchelement3s = NULL;
8179 rsurface.batchelement3s_indexbuffer = NULL;
8180 rsurface.batchelement3s_bufferoffset = 0;
8181 rsurface.passcolor4f = NULL;
8182 rsurface.passcolor4f_vertexbuffer = NULL;
8183 rsurface.passcolor4f_bufferoffset = 0;
8186 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)
8188 rsurface.entity = r_refdef.scene.worldentity;
8189 rsurface.skeleton = NULL;
8190 rsurface.ent_skinnum = 0;
8191 rsurface.ent_qwskin = -1;
8192 rsurface.ent_flags = entflags;
8193 rsurface.shadertime = r_refdef.scene.time - shadertime;
8194 rsurface.modelnumvertices = numvertices;
8195 rsurface.modelnumtriangles = numtriangles;
8196 rsurface.matrix = *matrix;
8197 rsurface.inversematrix = *inversematrix;
8198 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8199 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8200 R_EntityMatrix(&rsurface.matrix);
8201 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8202 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8203 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8204 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8205 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8206 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8207 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8208 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8209 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8210 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8211 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8212 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8213 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);
8214 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8215 rsurface.frameblend[0].lerp = 1;
8216 rsurface.ent_alttextures = false;
8217 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8218 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8221 rsurface.modelvertex3f = (float *)vertex3f;
8222 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8223 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8224 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8226 else if (wantnormals)
8228 rsurface.modelvertex3f = (float *)vertex3f;
8229 rsurface.modelsvector3f = NULL;
8230 rsurface.modeltvector3f = NULL;
8231 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8235 rsurface.modelvertex3f = (float *)vertex3f;
8236 rsurface.modelsvector3f = NULL;
8237 rsurface.modeltvector3f = NULL;
8238 rsurface.modelnormal3f = NULL;
8240 rsurface.modelvertexmesh = NULL;
8241 rsurface.modelvertexmeshbuffer = NULL;
8242 rsurface.modelvertex3fbuffer = NULL;
8243 rsurface.modelvertex3f_vertexbuffer = 0;
8244 rsurface.modelvertex3f_bufferoffset = 0;
8245 rsurface.modelsvector3f_vertexbuffer = 0;
8246 rsurface.modelsvector3f_bufferoffset = 0;
8247 rsurface.modeltvector3f_vertexbuffer = 0;
8248 rsurface.modeltvector3f_bufferoffset = 0;
8249 rsurface.modelnormal3f_vertexbuffer = 0;
8250 rsurface.modelnormal3f_bufferoffset = 0;
8251 rsurface.modelgeneratedvertex = true;
8252 rsurface.modellightmapcolor4f = (float *)color4f;
8253 rsurface.modellightmapcolor4f_vertexbuffer = 0;
8254 rsurface.modellightmapcolor4f_bufferoffset = 0;
8255 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
8256 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8257 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8258 rsurface.modeltexcoordlightmap2f = NULL;
8259 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8260 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8261 rsurface.modelelement3i = (int *)element3i;
8262 rsurface.modelelement3i_indexbuffer = NULL;
8263 rsurface.modelelement3i_bufferoffset = 0;
8264 rsurface.modelelement3s = (unsigned short *)element3s;
8265 rsurface.modelelement3s_indexbuffer = NULL;
8266 rsurface.modelelement3s_bufferoffset = 0;
8267 rsurface.modellightmapoffsets = NULL;
8268 rsurface.modelsurfaces = NULL;
8269 rsurface.batchgeneratedvertex = false;
8270 rsurface.batchfirstvertex = 0;
8271 rsurface.batchnumvertices = 0;
8272 rsurface.batchfirsttriangle = 0;
8273 rsurface.batchnumtriangles = 0;
8274 rsurface.batchvertex3f = NULL;
8275 rsurface.batchvertex3f_vertexbuffer = NULL;
8276 rsurface.batchvertex3f_bufferoffset = 0;
8277 rsurface.batchsvector3f = NULL;
8278 rsurface.batchsvector3f_vertexbuffer = NULL;
8279 rsurface.batchsvector3f_bufferoffset = 0;
8280 rsurface.batchtvector3f = NULL;
8281 rsurface.batchtvector3f_vertexbuffer = NULL;
8282 rsurface.batchtvector3f_bufferoffset = 0;
8283 rsurface.batchnormal3f = NULL;
8284 rsurface.batchnormal3f_vertexbuffer = NULL;
8285 rsurface.batchnormal3f_bufferoffset = 0;
8286 rsurface.batchlightmapcolor4f = NULL;
8287 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8288 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8289 rsurface.batchtexcoordtexture2f = NULL;
8290 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8291 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8292 rsurface.batchtexcoordlightmap2f = NULL;
8293 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8294 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8295 rsurface.batchvertexmesh = NULL;
8296 rsurface.batchvertexmeshbuffer = NULL;
8297 rsurface.batchvertex3fbuffer = NULL;
8298 rsurface.batchelement3i = NULL;
8299 rsurface.batchelement3i_indexbuffer = NULL;
8300 rsurface.batchelement3i_bufferoffset = 0;
8301 rsurface.batchelement3s = NULL;
8302 rsurface.batchelement3s_indexbuffer = NULL;
8303 rsurface.batchelement3s_bufferoffset = 0;
8304 rsurface.passcolor4f = NULL;
8305 rsurface.passcolor4f_vertexbuffer = NULL;
8306 rsurface.passcolor4f_bufferoffset = 0;
8308 if (rsurface.modelnumvertices && rsurface.modelelement3i)
8310 if ((wantnormals || wanttangents) && !normal3f)
8312 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8313 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8315 if (wanttangents && !svector3f)
8317 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8318 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8319 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8324 float RSurf_FogPoint(const float *v)
8326 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8327 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8328 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8329 float FogHeightFade = r_refdef.fogheightfade;
8331 unsigned int fogmasktableindex;
8332 if (r_refdef.fogplaneviewabove)
8333 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8335 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8336 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8337 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8340 float RSurf_FogVertex(const float *v)
8342 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8343 float FogPlaneViewDist = rsurface.fogplaneviewdist;
8344 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8345 float FogHeightFade = rsurface.fogheightfade;
8347 unsigned int fogmasktableindex;
8348 if (r_refdef.fogplaneviewabove)
8349 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8351 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8352 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8353 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8356 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8359 for (i = 0;i < numelements;i++)
8360 outelement3i[i] = inelement3i[i] + adjust;
8363 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8364 extern cvar_t gl_vbo;
8365 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8373 int surfacefirsttriangle;
8374 int surfacenumtriangles;
8375 int surfacefirstvertex;
8376 int surfaceendvertex;
8377 int surfacenumvertices;
8378 int batchnumvertices;
8379 int batchnumtriangles;
8383 qboolean dynamicvertex;
8387 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8389 q3shaderinfo_deform_t *deform;
8390 const msurface_t *surface, *firstsurface;
8391 r_vertexmesh_t *vertexmesh;
8392 if (!texturenumsurfaces)
8394 // find vertex range of this surface batch
8396 firstsurface = texturesurfacelist[0];
8397 firsttriangle = firstsurface->num_firsttriangle;
8398 batchnumvertices = 0;
8399 batchnumtriangles = 0;
8400 firstvertex = endvertex = firstsurface->num_firstvertex;
8401 for (i = 0;i < texturenumsurfaces;i++)
8403 surface = texturesurfacelist[i];
8404 if (surface != firstsurface + i)
8406 surfacefirstvertex = surface->num_firstvertex;
8407 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8408 surfacenumvertices = surface->num_vertices;
8409 surfacenumtriangles = surface->num_triangles;
8410 if (firstvertex > surfacefirstvertex)
8411 firstvertex = surfacefirstvertex;
8412 if (endvertex < surfaceendvertex)
8413 endvertex = surfaceendvertex;
8414 batchnumvertices += surfacenumvertices;
8415 batchnumtriangles += surfacenumtriangles;
8418 // we now know the vertex range used, and if there are any gaps in it
8419 rsurface.batchfirstvertex = firstvertex;
8420 rsurface.batchnumvertices = endvertex - firstvertex;
8421 rsurface.batchfirsttriangle = firsttriangle;
8422 rsurface.batchnumtriangles = batchnumtriangles;
8424 // this variable holds flags for which properties have been updated that
8425 // may require regenerating vertexmesh array...
8428 // check if any dynamic vertex processing must occur
8429 dynamicvertex = false;
8431 // if there is a chance of animated vertex colors, it's a dynamic batch
8432 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8434 dynamicvertex = true;
8435 batchneed |= BATCHNEED_NOGAPS;
8436 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8439 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8441 switch (deform->deform)
8444 case Q3DEFORM_PROJECTIONSHADOW:
8445 case Q3DEFORM_TEXT0:
8446 case Q3DEFORM_TEXT1:
8447 case Q3DEFORM_TEXT2:
8448 case Q3DEFORM_TEXT3:
8449 case Q3DEFORM_TEXT4:
8450 case Q3DEFORM_TEXT5:
8451 case Q3DEFORM_TEXT6:
8452 case Q3DEFORM_TEXT7:
8455 case Q3DEFORM_AUTOSPRITE:
8456 dynamicvertex = true;
8457 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8458 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8460 case Q3DEFORM_AUTOSPRITE2:
8461 dynamicvertex = true;
8462 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8463 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8465 case Q3DEFORM_NORMAL:
8466 dynamicvertex = true;
8467 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8468 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8471 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8472 break; // if wavefunc is a nop, ignore this transform
8473 dynamicvertex = true;
8474 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8475 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8477 case Q3DEFORM_BULGE:
8478 dynamicvertex = true;
8479 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8480 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8483 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8484 break; // if wavefunc is a nop, ignore this transform
8485 dynamicvertex = true;
8486 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8487 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8491 switch(rsurface.texture->tcgen.tcgen)
8494 case Q3TCGEN_TEXTURE:
8496 case Q3TCGEN_LIGHTMAP:
8497 dynamicvertex = true;
8498 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8499 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8501 case Q3TCGEN_VECTOR:
8502 dynamicvertex = true;
8503 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8504 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8506 case Q3TCGEN_ENVIRONMENT:
8507 dynamicvertex = true;
8508 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8509 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8512 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8514 dynamicvertex = true;
8515 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8516 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8519 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8521 dynamicvertex = true;
8522 batchneed |= BATCHNEED_NOGAPS;
8523 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8526 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8528 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8529 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
8530 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
8531 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
8532 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8533 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8534 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8537 // when the model data has no vertex buffer (dynamic mesh), we need to
8539 if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8540 batchneed |= BATCHNEED_NOGAPS;
8542 // if needsupdate, we have to do a dynamic vertex batch for sure
8543 if (needsupdate & batchneed)
8544 dynamicvertex = true;
8546 // see if we need to build vertexmesh from arrays
8547 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8548 dynamicvertex = true;
8550 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8551 // also some drivers strongly dislike firstvertex
8552 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8553 dynamicvertex = true;
8555 rsurface.batchvertex3f = rsurface.modelvertex3f;
8556 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8557 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8558 rsurface.batchsvector3f = rsurface.modelsvector3f;
8559 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8560 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8561 rsurface.batchtvector3f = rsurface.modeltvector3f;
8562 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8563 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8564 rsurface.batchnormal3f = rsurface.modelnormal3f;
8565 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8566 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8567 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8568 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
8569 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8570 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8571 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
8572 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
8573 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8574 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8575 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8576 rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8577 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8578 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8579 rsurface.batchelement3i = rsurface.modelelement3i;
8580 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8581 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8582 rsurface.batchelement3s = rsurface.modelelement3s;
8583 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8584 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8586 // if any dynamic vertex processing has to occur in software, we copy the
8587 // entire surface list together before processing to rebase the vertices
8588 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8590 // if any gaps exist and we do not have a static vertex buffer, we have to
8591 // copy the surface list together to avoid wasting upload bandwidth on the
8592 // vertices in the gaps.
8594 // if gaps exist and we have a static vertex buffer, we still have to
8595 // combine the index buffer ranges into one dynamic index buffer.
8597 // in all cases we end up with data that can be drawn in one call.
8601 // static vertex data, just set pointers...
8602 rsurface.batchgeneratedvertex = false;
8603 // if there are gaps, we want to build a combined index buffer,
8604 // otherwise use the original static buffer with an appropriate offset
8607 // build a new triangle elements array for this batch
8608 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8609 rsurface.batchfirsttriangle = 0;
8611 for (i = 0;i < texturenumsurfaces;i++)
8613 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8614 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8615 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8616 numtriangles += surfacenumtriangles;
8618 rsurface.batchelement3i_indexbuffer = NULL;
8619 rsurface.batchelement3i_bufferoffset = 0;
8620 rsurface.batchelement3s = NULL;
8621 rsurface.batchelement3s_indexbuffer = NULL;
8622 rsurface.batchelement3s_bufferoffset = 0;
8623 if (endvertex <= 65536)
8625 // make a 16bit (unsigned short) index array if possible
8626 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8627 for (i = 0;i < numtriangles*3;i++)
8628 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8634 // something needs software processing, do it for real...
8635 // we only directly handle separate array data in this case and then
8636 // generate interleaved data if needed...
8637 rsurface.batchgeneratedvertex = true;
8639 // now copy the vertex data into a combined array and make an index array
8640 // (this is what Quake3 does all the time)
8641 //if (gaps || rsurface.batchfirstvertex)
8643 rsurface.batchvertex3fbuffer = NULL;
8644 rsurface.batchvertexmesh = NULL;
8645 rsurface.batchvertexmeshbuffer = NULL;
8646 rsurface.batchvertex3f = NULL;
8647 rsurface.batchvertex3f_vertexbuffer = NULL;
8648 rsurface.batchvertex3f_bufferoffset = 0;
8649 rsurface.batchsvector3f = NULL;
8650 rsurface.batchsvector3f_vertexbuffer = NULL;
8651 rsurface.batchsvector3f_bufferoffset = 0;
8652 rsurface.batchtvector3f = NULL;
8653 rsurface.batchtvector3f_vertexbuffer = NULL;
8654 rsurface.batchtvector3f_bufferoffset = 0;
8655 rsurface.batchnormal3f = NULL;
8656 rsurface.batchnormal3f_vertexbuffer = NULL;
8657 rsurface.batchnormal3f_bufferoffset = 0;
8658 rsurface.batchlightmapcolor4f = NULL;
8659 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8660 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8661 rsurface.batchtexcoordtexture2f = NULL;
8662 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8663 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8664 rsurface.batchtexcoordlightmap2f = NULL;
8665 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8666 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8667 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8668 rsurface.batchelement3i_indexbuffer = NULL;
8669 rsurface.batchelement3i_bufferoffset = 0;
8670 rsurface.batchelement3s = NULL;
8671 rsurface.batchelement3s_indexbuffer = NULL;
8672 rsurface.batchelement3s_bufferoffset = 0;
8673 // we'll only be setting up certain arrays as needed
8674 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8675 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8676 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8677 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8678 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8679 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8680 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8682 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8683 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8685 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8686 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8687 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8688 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8689 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8690 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8693 for (i = 0;i < texturenumsurfaces;i++)
8695 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8696 surfacenumvertices = texturesurfacelist[i]->num_vertices;
8697 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8698 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8699 // copy only the data requested
8700 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8701 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8702 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8704 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8706 if (rsurface.batchvertex3f)
8707 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8709 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8711 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8713 if (rsurface.modelnormal3f)
8714 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8716 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8718 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8720 if (rsurface.modelsvector3f)
8722 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8723 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8727 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8728 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8731 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8733 if (rsurface.modellightmapcolor4f)
8734 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8736 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
8738 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8740 if (rsurface.modeltexcoordtexture2f)
8741 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8743 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8745 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8747 if (rsurface.modeltexcoordlightmap2f)
8748 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8750 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8753 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8754 numvertices += surfacenumvertices;
8755 numtriangles += surfacenumtriangles;
8758 // generate a 16bit index array as well if possible
8759 // (in general, dynamic batches fit)
8760 if (numvertices <= 65536)
8762 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8763 for (i = 0;i < numtriangles*3;i++)
8764 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8767 // since we've copied everything, the batch now starts at 0
8768 rsurface.batchfirstvertex = 0;
8769 rsurface.batchnumvertices = batchnumvertices;
8770 rsurface.batchfirsttriangle = 0;
8771 rsurface.batchnumtriangles = batchnumtriangles;
8774 // q1bsp surfaces rendered in vertex color mode have to have colors
8775 // calculated based on lightstyles
8776 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8778 // generate color arrays for the surfaces in this list
8783 const unsigned char *lm;
8784 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8785 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8786 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8788 for (i = 0;i < texturenumsurfaces;i++)
8790 surface = texturesurfacelist[i];
8791 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8792 surfacenumvertices = surface->num_vertices;
8793 if (surface->lightmapinfo->samples)
8795 for (j = 0;j < surfacenumvertices;j++)
8797 lm = surface->lightmapinfo->samples + offsets[j];
8798 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8799 VectorScale(lm, scale, c);
8800 if (surface->lightmapinfo->styles[1] != 255)
8802 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8804 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8805 VectorMA(c, scale, lm, c);
8806 if (surface->lightmapinfo->styles[2] != 255)
8809 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8810 VectorMA(c, scale, lm, c);
8811 if (surface->lightmapinfo->styles[3] != 255)
8814 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8815 VectorMA(c, scale, lm, c);
8822 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);
8828 for (j = 0;j < surfacenumvertices;j++)
8830 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8837 // if vertices are deformed (sprite flares and things in maps, possibly
8838 // water waves, bulges and other deformations), modify the copied vertices
8840 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8842 switch (deform->deform)
8845 case Q3DEFORM_PROJECTIONSHADOW:
8846 case Q3DEFORM_TEXT0:
8847 case Q3DEFORM_TEXT1:
8848 case Q3DEFORM_TEXT2:
8849 case Q3DEFORM_TEXT3:
8850 case Q3DEFORM_TEXT4:
8851 case Q3DEFORM_TEXT5:
8852 case Q3DEFORM_TEXT6:
8853 case Q3DEFORM_TEXT7:
8856 case Q3DEFORM_AUTOSPRITE:
8857 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8858 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8859 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8860 VectorNormalize(newforward);
8861 VectorNormalize(newright);
8862 VectorNormalize(newup);
8863 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8864 // rsurface.batchvertex3f_vertexbuffer = NULL;
8865 // rsurface.batchvertex3f_bufferoffset = 0;
8866 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8867 // rsurface.batchsvector3f_vertexbuffer = NULL;
8868 // rsurface.batchsvector3f_bufferoffset = 0;
8869 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8870 // rsurface.batchtvector3f_vertexbuffer = NULL;
8871 // rsurface.batchtvector3f_bufferoffset = 0;
8872 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8873 // rsurface.batchnormal3f_vertexbuffer = NULL;
8874 // rsurface.batchnormal3f_bufferoffset = 0;
8875 // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
8876 if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
8877 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8878 if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
8879 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);
8880 // a single autosprite surface can contain multiple sprites...
8881 for (j = 0;j < batchnumvertices - 3;j += 4)
8883 VectorClear(center);
8884 for (i = 0;i < 4;i++)
8885 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8886 VectorScale(center, 0.25f, center);
8887 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8888 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8889 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8890 for (i = 0;i < 4;i++)
8892 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8893 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8896 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8897 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8898 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);
8900 case Q3DEFORM_AUTOSPRITE2:
8901 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8902 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8903 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8904 VectorNormalize(newforward);
8905 VectorNormalize(newright);
8906 VectorNormalize(newup);
8907 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8908 // rsurface.batchvertex3f_vertexbuffer = NULL;
8909 // rsurface.batchvertex3f_bufferoffset = 0;
8911 const float *v1, *v2;
8921 memset(shortest, 0, sizeof(shortest));
8922 // a single autosprite surface can contain multiple sprites...
8923 for (j = 0;j < batchnumvertices - 3;j += 4)
8925 VectorClear(center);
8926 for (i = 0;i < 4;i++)
8927 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8928 VectorScale(center, 0.25f, center);
8929 // find the two shortest edges, then use them to define the
8930 // axis vectors for rotating around the central axis
8931 for (i = 0;i < 6;i++)
8933 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8934 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8935 l = VectorDistance2(v1, v2);
8936 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8938 l += (1.0f / 1024.0f);
8939 if (shortest[0].length2 > l || i == 0)
8941 shortest[1] = shortest[0];
8942 shortest[0].length2 = l;
8943 shortest[0].v1 = v1;
8944 shortest[0].v2 = v2;
8946 else if (shortest[1].length2 > l || i == 1)
8948 shortest[1].length2 = l;
8949 shortest[1].v1 = v1;
8950 shortest[1].v2 = v2;
8953 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8954 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8955 // this calculates the right vector from the shortest edge
8956 // and the up vector from the edge midpoints
8957 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8958 VectorNormalize(right);
8959 VectorSubtract(end, start, up);
8960 VectorNormalize(up);
8961 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8962 VectorSubtract(rsurface.localvieworigin, center, forward);
8963 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8964 VectorNegate(forward, forward);
8965 VectorReflect(forward, 0, up, forward);
8966 VectorNormalize(forward);
8967 CrossProduct(up, forward, newright);
8968 VectorNormalize(newright);
8969 // rotate the quad around the up axis vector, this is made
8970 // especially easy by the fact we know the quad is flat,
8971 // so we only have to subtract the center position and
8972 // measure distance along the right vector, and then
8973 // multiply that by the newright vector and add back the
8975 // we also need to subtract the old position to undo the
8976 // displacement from the center, which we do with a
8977 // DotProduct, the subtraction/addition of center is also
8978 // optimized into DotProducts here
8979 l = DotProduct(right, center);
8980 for (i = 0;i < 4;i++)
8982 v1 = rsurface.batchvertex3f + 3*(j+i);
8983 f = DotProduct(right, v1) - l;
8984 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8988 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8990 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8991 // rsurface.batchnormal3f_vertexbuffer = NULL;
8992 // rsurface.batchnormal3f_bufferoffset = 0;
8993 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8995 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8997 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8998 // rsurface.batchsvector3f_vertexbuffer = NULL;
8999 // rsurface.batchsvector3f_bufferoffset = 0;
9000 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9001 // rsurface.batchtvector3f_vertexbuffer = NULL;
9002 // rsurface.batchtvector3f_bufferoffset = 0;
9003 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);
9006 case Q3DEFORM_NORMAL:
9007 // deform the normals to make reflections wavey
9008 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9009 rsurface.batchnormal3f_vertexbuffer = NULL;
9010 rsurface.batchnormal3f_bufferoffset = 0;
9011 for (j = 0;j < batchnumvertices;j++)
9014 float *normal = rsurface.batchnormal3f + 3*j;
9015 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9016 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9017 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9018 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9019 VectorNormalize(normal);
9021 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9023 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9024 // rsurface.batchsvector3f_vertexbuffer = NULL;
9025 // rsurface.batchsvector3f_bufferoffset = 0;
9026 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9027 // rsurface.batchtvector3f_vertexbuffer = NULL;
9028 // rsurface.batchtvector3f_bufferoffset = 0;
9029 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);
9033 // deform vertex array to make wavey water and flags and such
9034 waveparms[0] = deform->waveparms[0];
9035 waveparms[1] = deform->waveparms[1];
9036 waveparms[2] = deform->waveparms[2];
9037 waveparms[3] = deform->waveparms[3];
9038 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9039 break; // if wavefunc is a nop, don't make a dynamic vertex array
9040 // this is how a divisor of vertex influence on deformation
9041 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9042 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9043 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9044 // rsurface.batchvertex3f_vertexbuffer = NULL;
9045 // rsurface.batchvertex3f_bufferoffset = 0;
9046 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9047 // rsurface.batchnormal3f_vertexbuffer = NULL;
9048 // rsurface.batchnormal3f_bufferoffset = 0;
9049 for (j = 0;j < batchnumvertices;j++)
9051 // if the wavefunc depends on time, evaluate it per-vertex
9054 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9055 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9057 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9059 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9060 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9061 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9063 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9064 // rsurface.batchsvector3f_vertexbuffer = NULL;
9065 // rsurface.batchsvector3f_bufferoffset = 0;
9066 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9067 // rsurface.batchtvector3f_vertexbuffer = NULL;
9068 // rsurface.batchtvector3f_bufferoffset = 0;
9069 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);
9072 case Q3DEFORM_BULGE:
9073 // deform vertex array to make the surface have moving bulges
9074 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9075 // rsurface.batchvertex3f_vertexbuffer = NULL;
9076 // rsurface.batchvertex3f_bufferoffset = 0;
9077 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9078 // rsurface.batchnormal3f_vertexbuffer = NULL;
9079 // rsurface.batchnormal3f_bufferoffset = 0;
9080 for (j = 0;j < batchnumvertices;j++)
9082 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9083 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9085 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9086 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9087 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9089 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9090 // rsurface.batchsvector3f_vertexbuffer = NULL;
9091 // rsurface.batchsvector3f_bufferoffset = 0;
9092 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9093 // rsurface.batchtvector3f_vertexbuffer = NULL;
9094 // rsurface.batchtvector3f_bufferoffset = 0;
9095 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);
9099 // deform vertex array
9100 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9101 break; // if wavefunc is a nop, don't make a dynamic vertex array
9102 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9103 VectorScale(deform->parms, scale, waveparms);
9104 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9105 // rsurface.batchvertex3f_vertexbuffer = NULL;
9106 // rsurface.batchvertex3f_bufferoffset = 0;
9107 for (j = 0;j < batchnumvertices;j++)
9108 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9113 // generate texcoords based on the chosen texcoord source
9114 switch(rsurface.texture->tcgen.tcgen)
9117 case Q3TCGEN_TEXTURE:
9119 case Q3TCGEN_LIGHTMAP:
9120 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9121 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9122 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9123 if (rsurface.batchtexcoordlightmap2f)
9124 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9126 case Q3TCGEN_VECTOR:
9127 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9128 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9129 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9130 for (j = 0;j < batchnumvertices;j++)
9132 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9133 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9136 case Q3TCGEN_ENVIRONMENT:
9137 // make environment reflections using a spheremap
9138 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9139 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9140 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9141 for (j = 0;j < batchnumvertices;j++)
9143 // identical to Q3A's method, but executed in worldspace so
9144 // carried models can be shiny too
9146 float viewer[3], d, reflected[3], worldreflected[3];
9148 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9149 // VectorNormalize(viewer);
9151 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9153 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9154 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9155 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9156 // note: this is proportinal to viewer, so we can normalize later
9158 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9159 VectorNormalize(worldreflected);
9161 // note: this sphere map only uses world x and z!
9162 // so positive and negative y will LOOK THE SAME.
9163 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9164 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9168 // the only tcmod that needs software vertex processing is turbulent, so
9169 // check for it here and apply the changes if needed
9170 // and we only support that as the first one
9171 // (handling a mixture of turbulent and other tcmods would be problematic
9172 // without punting it entirely to a software path)
9173 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9175 amplitude = rsurface.texture->tcmods[0].parms[1];
9176 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9177 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9178 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9179 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9180 for (j = 0;j < batchnumvertices;j++)
9182 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);
9183 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9187 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9189 // convert the modified arrays to vertex structs
9190 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9191 // rsurface.batchvertexmeshbuffer = NULL;
9192 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9193 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9194 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9195 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9196 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9197 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9198 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9200 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9202 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9203 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9206 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9207 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9208 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9209 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9210 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9211 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9212 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9213 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9214 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9218 void RSurf_DrawBatch(void)
9220 // sometimes a zero triangle surface (usually a degenerate patch) makes it
9221 // through the pipeline, killing it earlier in the pipeline would have
9222 // per-surface overhead rather than per-batch overhead, so it's best to
9223 // reject it here, before it hits glDraw.
9224 if (rsurface.batchnumtriangles == 0)
9227 // batch debugging code
9228 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9234 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9235 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9238 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9240 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9242 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9243 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);
9250 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);
9253 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9255 // pick the closest matching water plane
9256 int planeindex, vertexindex, bestplaneindex = -1;
9260 r_waterstate_waterplane_t *p;
9261 qboolean prepared = false;
9263 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9265 if(p->camera_entity != rsurface.texture->camera_entity)
9270 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9272 if(rsurface.batchnumvertices == 0)
9275 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9277 Matrix4x4_Transform(&rsurface.matrix, v, vert);
9278 d += fabs(PlaneDiff(vert, &p->plane));
9280 if (bestd > d || bestplaneindex < 0)
9283 bestplaneindex = planeindex;
9286 return bestplaneindex;
9287 // NOTE: this MAY return a totally unrelated water plane; we can ignore
9288 // this situation though, as it might be better to render single larger
9289 // batches with useless stuff (backface culled for example) than to
9290 // render multiple smaller batches
9293 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9296 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9297 rsurface.passcolor4f_vertexbuffer = 0;
9298 rsurface.passcolor4f_bufferoffset = 0;
9299 for (i = 0;i < rsurface.batchnumvertices;i++)
9300 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9303 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9310 if (rsurface.passcolor4f)
9312 // generate color arrays
9313 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9314 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9315 rsurface.passcolor4f_vertexbuffer = 0;
9316 rsurface.passcolor4f_bufferoffset = 0;
9317 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)
9319 f = RSurf_FogVertex(v);
9328 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9329 rsurface.passcolor4f_vertexbuffer = 0;
9330 rsurface.passcolor4f_bufferoffset = 0;
9331 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9333 f = RSurf_FogVertex(v);
9342 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9349 if (!rsurface.passcolor4f)
9351 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9352 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9353 rsurface.passcolor4f_vertexbuffer = 0;
9354 rsurface.passcolor4f_bufferoffset = 0;
9355 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)
9357 f = RSurf_FogVertex(v);
9358 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9359 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9360 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9365 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9370 if (!rsurface.passcolor4f)
9372 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9373 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9374 rsurface.passcolor4f_vertexbuffer = 0;
9375 rsurface.passcolor4f_bufferoffset = 0;
9376 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9385 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9390 if (!rsurface.passcolor4f)
9392 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9393 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9394 rsurface.passcolor4f_vertexbuffer = 0;
9395 rsurface.passcolor4f_bufferoffset = 0;
9396 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9398 c2[0] = c[0] + r_refdef.scene.ambient;
9399 c2[1] = c[1] + r_refdef.scene.ambient;
9400 c2[2] = c[2] + r_refdef.scene.ambient;
9405 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9408 rsurface.passcolor4f = NULL;
9409 rsurface.passcolor4f_vertexbuffer = 0;
9410 rsurface.passcolor4f_bufferoffset = 0;
9411 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9412 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9413 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9414 GL_Color(r, g, b, a);
9415 R_Mesh_TexBind(0, rsurface.lightmaptexture);
9419 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9421 // TODO: optimize applyfog && applycolor case
9422 // just apply fog if necessary, and tint the fog color array if necessary
9423 rsurface.passcolor4f = NULL;
9424 rsurface.passcolor4f_vertexbuffer = 0;
9425 rsurface.passcolor4f_bufferoffset = 0;
9426 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9427 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9428 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9429 GL_Color(r, g, b, a);
9433 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9436 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9437 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9438 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9439 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9440 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9441 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9442 GL_Color(r, g, b, a);
9446 static void RSurf_DrawBatch_GL11_ClampColor(void)
9451 if (!rsurface.passcolor4f)
9453 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9455 c2[0] = bound(0.0f, c1[0], 1.0f);
9456 c2[1] = bound(0.0f, c1[1], 1.0f);
9457 c2[2] = bound(0.0f, c1[2], 1.0f);
9458 c2[3] = bound(0.0f, c1[3], 1.0f);
9462 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9472 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9473 rsurface.passcolor4f_vertexbuffer = 0;
9474 rsurface.passcolor4f_bufferoffset = 0;
9475 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)
9477 f = -DotProduct(r_refdef.view.forward, n);
9479 f = f * 0.85 + 0.15; // work around so stuff won't get black
9480 f *= r_refdef.lightmapintensity;
9481 Vector4Set(c, f, f, f, 1);
9485 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9487 RSurf_DrawBatch_GL11_ApplyFakeLight();
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_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9503 vec3_t ambientcolor;
9504 vec3_t diffusecolor;
9508 VectorCopy(rsurface.modellight_lightdir, lightdir);
9509 f = 0.5f * r_refdef.lightmapintensity;
9510 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9511 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9512 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9513 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9514 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9515 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9517 if (VectorLength2(diffusecolor) > 0)
9519 // q3-style directional shading
9520 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9521 rsurface.passcolor4f_vertexbuffer = 0;
9522 rsurface.passcolor4f_bufferoffset = 0;
9523 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)
9525 if ((f = DotProduct(n, lightdir)) > 0)
9526 VectorMA(ambientcolor, f, diffusecolor, c);
9528 VectorCopy(ambientcolor, c);
9535 *applycolor = false;
9539 *r = ambientcolor[0];
9540 *g = ambientcolor[1];
9541 *b = ambientcolor[2];
9542 rsurface.passcolor4f = NULL;
9543 rsurface.passcolor4f_vertexbuffer = 0;
9544 rsurface.passcolor4f_bufferoffset = 0;
9548 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9550 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9551 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9552 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9553 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9554 GL_Color(r, g, b, a);
9558 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9566 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9567 rsurface.passcolor4f_vertexbuffer = 0;
9568 rsurface.passcolor4f_bufferoffset = 0;
9570 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9572 f = 1 - RSurf_FogVertex(v);
9580 void RSurf_SetupDepthAndCulling(void)
9582 // submodels are biased to avoid z-fighting with world surfaces that they
9583 // may be exactly overlapping (avoids z-fighting artifacts on certain
9584 // doors and things in Quake maps)
9585 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9586 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9587 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9588 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9591 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9593 // transparent sky would be ridiculous
9594 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9596 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
9597 skyrenderlater = true;
9598 RSurf_SetupDepthAndCulling();
9600 // LordHavoc: HalfLife maps have freaky skypolys so don't use
9601 // skymasking on them, and Quake3 never did sky masking (unlike
9602 // software Quake and software Quake2), so disable the sky masking
9603 // in Quake3 maps as it causes problems with q3map2 sky tricks,
9604 // and skymasking also looks very bad when noclipping outside the
9605 // level, so don't use it then either.
9606 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
9608 R_Mesh_ResetTextureState();
9609 if (skyrendermasked)
9611 R_SetupShader_DepthOrShadow(false);
9612 // depth-only (masking)
9613 GL_ColorMask(0,0,0,0);
9614 // just to make sure that braindead drivers don't draw
9615 // anything despite that colormask...
9616 GL_BlendFunc(GL_ZERO, GL_ONE);
9617 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9618 if (rsurface.batchvertex3fbuffer)
9619 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9621 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9625 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
9627 GL_BlendFunc(GL_ONE, GL_ZERO);
9628 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9629 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9630 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9633 if (skyrendermasked)
9634 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9636 R_Mesh_ResetTextureState();
9637 GL_Color(1, 1, 1, 1);
9640 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9641 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9642 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9644 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9648 // render screenspace normalmap to texture
9650 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
9654 // bind lightmap texture
9656 // water/refraction/reflection/camera surfaces have to be handled specially
9657 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9659 int start, end, startplaneindex;
9660 for (start = 0;start < texturenumsurfaces;start = end)
9662 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9663 if(startplaneindex < 0)
9665 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9666 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9670 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9672 // now that we have a batch using the same planeindex, render it
9673 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9675 // render water or distortion background
9677 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);
9679 // blend surface on top
9680 GL_DepthMask(false);
9681 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
9684 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9686 // render surface with reflection texture as input
9687 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9688 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);
9695 // render surface batch normally
9696 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9697 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);
9701 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9703 // OpenGL 1.3 path - anything not completely ancient
9704 qboolean applycolor;
9707 const texturelayer_t *layer;
9708 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);
9709 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9711 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9714 int layertexrgbscale;
9715 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9717 if (layerindex == 0)
9721 GL_AlphaTest(false);
9722 GL_DepthFunc(GL_EQUAL);
9725 GL_DepthMask(layer->depthmask && writedepth);
9726 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9727 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9729 layertexrgbscale = 4;
9730 VectorScale(layer->color, 0.25f, layercolor);
9732 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9734 layertexrgbscale = 2;
9735 VectorScale(layer->color, 0.5f, layercolor);
9739 layertexrgbscale = 1;
9740 VectorScale(layer->color, 1.0f, layercolor);
9742 layercolor[3] = layer->color[3];
9743 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9744 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9745 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9746 switch (layer->type)
9748 case TEXTURELAYERTYPE_LITTEXTURE:
9749 // single-pass lightmapped texture with 2x rgbscale
9750 R_Mesh_TexBind(0, r_texture_white);
9751 R_Mesh_TexMatrix(0, NULL);
9752 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9753 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9754 R_Mesh_TexBind(1, layer->texture);
9755 R_Mesh_TexMatrix(1, &layer->texmatrix);
9756 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9757 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9758 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9759 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9760 else if (FAKELIGHT_ENABLED)
9761 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9762 else if (rsurface.uselightmaptexture)
9763 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9765 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9767 case TEXTURELAYERTYPE_TEXTURE:
9768 // singletexture unlit texture with transparency support
9769 R_Mesh_TexBind(0, layer->texture);
9770 R_Mesh_TexMatrix(0, &layer->texmatrix);
9771 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9772 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9773 R_Mesh_TexBind(1, 0);
9774 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9775 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9777 case TEXTURELAYERTYPE_FOG:
9778 // singletexture fogging
9781 R_Mesh_TexBind(0, layer->texture);
9782 R_Mesh_TexMatrix(0, &layer->texmatrix);
9783 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9784 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9788 R_Mesh_TexBind(0, 0);
9789 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9791 R_Mesh_TexBind(1, 0);
9792 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9793 // generate a color array for the fog pass
9794 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9795 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9799 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9802 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9804 GL_DepthFunc(GL_LEQUAL);
9805 GL_AlphaTest(false);
9809 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9811 // OpenGL 1.1 - crusty old voodoo path
9814 const texturelayer_t *layer;
9815 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);
9816 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9818 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9820 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9822 if (layerindex == 0)
9826 GL_AlphaTest(false);
9827 GL_DepthFunc(GL_EQUAL);
9830 GL_DepthMask(layer->depthmask && writedepth);
9831 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9832 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9833 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9834 switch (layer->type)
9836 case TEXTURELAYERTYPE_LITTEXTURE:
9837 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9839 // two-pass lit texture with 2x rgbscale
9840 // first the lightmap pass
9841 R_Mesh_TexBind(0, r_texture_white);
9842 R_Mesh_TexMatrix(0, NULL);
9843 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9844 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9845 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9846 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9847 else if (FAKELIGHT_ENABLED)
9848 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9849 else if (rsurface.uselightmaptexture)
9850 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9852 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9853 // then apply the texture to it
9854 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9855 R_Mesh_TexBind(0, layer->texture);
9856 R_Mesh_TexMatrix(0, &layer->texmatrix);
9857 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9858 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9859 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);
9863 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9864 R_Mesh_TexBind(0, layer->texture);
9865 R_Mesh_TexMatrix(0, &layer->texmatrix);
9866 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9867 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9868 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9869 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);
9871 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);
9874 case TEXTURELAYERTYPE_TEXTURE:
9875 // singletexture unlit texture with transparency support
9876 R_Mesh_TexBind(0, layer->texture);
9877 R_Mesh_TexMatrix(0, &layer->texmatrix);
9878 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9879 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9880 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);
9882 case TEXTURELAYERTYPE_FOG:
9883 // singletexture fogging
9886 R_Mesh_TexBind(0, layer->texture);
9887 R_Mesh_TexMatrix(0, &layer->texmatrix);
9888 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9889 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9893 R_Mesh_TexBind(0, 0);
9894 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9896 // generate a color array for the fog pass
9897 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9898 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9902 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9905 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9907 GL_DepthFunc(GL_LEQUAL);
9908 GL_AlphaTest(false);
9912 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9916 r_vertexgeneric_t *batchvertex;
9919 // R_Mesh_ResetTextureState();
9920 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
9922 if(rsurface.texture && rsurface.texture->currentskinframe)
9924 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9925 c[3] *= rsurface.texture->currentalpha;
9935 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9937 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9938 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9939 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9942 // brighten it up (as texture value 127 means "unlit")
9943 c[0] *= 2 * r_refdef.view.colorscale;
9944 c[1] *= 2 * r_refdef.view.colorscale;
9945 c[2] *= 2 * r_refdef.view.colorscale;
9947 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9948 c[3] *= r_wateralpha.value;
9950 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9952 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9953 GL_DepthMask(false);
9955 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9957 GL_BlendFunc(GL_ONE, GL_ONE);
9958 GL_DepthMask(false);
9960 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9962 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9963 GL_DepthMask(false);
9965 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9967 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9968 GL_DepthMask(false);
9972 GL_BlendFunc(GL_ONE, GL_ZERO);
9973 GL_DepthMask(writedepth);
9976 if (r_showsurfaces.integer == 3)
9978 rsurface.passcolor4f = NULL;
9980 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9982 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9984 rsurface.passcolor4f = NULL;
9985 rsurface.passcolor4f_vertexbuffer = 0;
9986 rsurface.passcolor4f_bufferoffset = 0;
9988 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9990 qboolean applycolor = true;
9993 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9995 r_refdef.lightmapintensity = 1;
9996 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9997 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9999 else if (FAKELIGHT_ENABLED)
10001 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10003 r_refdef.lightmapintensity = r_fakelight_intensity.value;
10004 RSurf_DrawBatch_GL11_ApplyFakeLight();
10005 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10009 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10011 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10012 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10013 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10016 if(!rsurface.passcolor4f)
10017 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10019 RSurf_DrawBatch_GL11_ApplyAmbient();
10020 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10021 if(r_refdef.fogenabled)
10022 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10023 RSurf_DrawBatch_GL11_ClampColor();
10025 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10026 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
10029 else if (!r_refdef.view.showdebug)
10031 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10032 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10033 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10035 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10036 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10038 R_Mesh_PrepareVertices_Generic_Unlock();
10041 else if (r_showsurfaces.integer == 4)
10043 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10044 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10045 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10047 unsigned char c = (vi << 3) * (1.0f / 256.0f);
10048 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10049 Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10051 R_Mesh_PrepareVertices_Generic_Unlock();
10054 else if (r_showsurfaces.integer == 2)
10057 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10058 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10059 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10061 unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10062 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10063 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10064 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10065 Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10066 Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10067 Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10069 R_Mesh_PrepareVertices_Generic_Unlock();
10070 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10074 int texturesurfaceindex;
10076 const msurface_t *surface;
10077 float surfacecolor4f[4];
10078 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10079 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10081 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10083 surface = texturesurfacelist[texturesurfaceindex];
10084 k = (int)(((size_t)surface) / sizeof(msurface_t));
10085 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10086 for (j = 0;j < surface->num_vertices;j++)
10088 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10089 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10093 R_Mesh_PrepareVertices_Generic_Unlock();
10098 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10101 RSurf_SetupDepthAndCulling();
10102 if (r_showsurfaces.integer)
10104 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10107 switch (vid.renderpath)
10109 case RENDERPATH_GL20:
10110 case RENDERPATH_D3D9:
10111 case RENDERPATH_D3D10:
10112 case RENDERPATH_D3D11:
10113 case RENDERPATH_SOFT:
10114 case RENDERPATH_GLES2:
10115 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10117 case RENDERPATH_GL13:
10118 case RENDERPATH_GLES1:
10119 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10121 case RENDERPATH_GL11:
10122 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10128 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10131 RSurf_SetupDepthAndCulling();
10132 if (r_showsurfaces.integer)
10134 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10137 switch (vid.renderpath)
10139 case RENDERPATH_GL20:
10140 case RENDERPATH_D3D9:
10141 case RENDERPATH_D3D10:
10142 case RENDERPATH_D3D11:
10143 case RENDERPATH_SOFT:
10144 case RENDERPATH_GLES2:
10145 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10147 case RENDERPATH_GL13:
10148 case RENDERPATH_GLES1:
10149 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10151 case RENDERPATH_GL11:
10152 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10158 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10161 int texturenumsurfaces, endsurface;
10162 texture_t *texture;
10163 const msurface_t *surface;
10164 const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10166 // if the model is static it doesn't matter what value we give for
10167 // wantnormals and wanttangents, so this logic uses only rules applicable
10168 // to a model, knowing that they are meaningless otherwise
10169 if (ent == r_refdef.scene.worldentity)
10170 RSurf_ActiveWorldEntity();
10171 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10172 RSurf_ActiveModelEntity(ent, false, false, false);
10175 switch (vid.renderpath)
10177 case RENDERPATH_GL20:
10178 case RENDERPATH_D3D9:
10179 case RENDERPATH_D3D10:
10180 case RENDERPATH_D3D11:
10181 case RENDERPATH_SOFT:
10182 case RENDERPATH_GLES2:
10183 RSurf_ActiveModelEntity(ent, true, true, false);
10185 case RENDERPATH_GL11:
10186 case RENDERPATH_GL13:
10187 case RENDERPATH_GLES1:
10188 RSurf_ActiveModelEntity(ent, true, false, false);
10193 if (r_transparentdepthmasking.integer)
10195 qboolean setup = false;
10196 for (i = 0;i < numsurfaces;i = j)
10199 surface = rsurface.modelsurfaces + surfacelist[i];
10200 texture = surface->texture;
10201 rsurface.texture = R_GetCurrentTexture(texture);
10202 rsurface.lightmaptexture = NULL;
10203 rsurface.deluxemaptexture = NULL;
10204 rsurface.uselightmaptexture = false;
10205 // scan ahead until we find a different texture
10206 endsurface = min(i + 1024, numsurfaces);
10207 texturenumsurfaces = 0;
10208 texturesurfacelist[texturenumsurfaces++] = surface;
10209 for (;j < endsurface;j++)
10211 surface = rsurface.modelsurfaces + surfacelist[j];
10212 if (texture != surface->texture)
10214 texturesurfacelist[texturenumsurfaces++] = surface;
10216 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10218 // render the range of surfaces as depth
10222 GL_ColorMask(0,0,0,0);
10224 GL_DepthTest(true);
10225 GL_BlendFunc(GL_ONE, GL_ZERO);
10226 GL_DepthMask(true);
10227 // R_Mesh_ResetTextureState();
10228 R_SetupShader_DepthOrShadow(false);
10230 RSurf_SetupDepthAndCulling();
10231 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10232 if (rsurface.batchvertex3fbuffer)
10233 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10235 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10239 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10242 for (i = 0;i < numsurfaces;i = j)
10245 surface = rsurface.modelsurfaces + surfacelist[i];
10246 texture = surface->texture;
10247 rsurface.texture = R_GetCurrentTexture(texture);
10248 // scan ahead until we find a different texture
10249 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10250 texturenumsurfaces = 0;
10251 texturesurfacelist[texturenumsurfaces++] = surface;
10252 if(FAKELIGHT_ENABLED)
10254 rsurface.lightmaptexture = NULL;
10255 rsurface.deluxemaptexture = NULL;
10256 rsurface.uselightmaptexture = false;
10257 for (;j < endsurface;j++)
10259 surface = rsurface.modelsurfaces + surfacelist[j];
10260 if (texture != surface->texture)
10262 texturesurfacelist[texturenumsurfaces++] = surface;
10267 rsurface.lightmaptexture = surface->lightmaptexture;
10268 rsurface.deluxemaptexture = surface->deluxemaptexture;
10269 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10270 for (;j < endsurface;j++)
10272 surface = rsurface.modelsurfaces + surfacelist[j];
10273 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10275 texturesurfacelist[texturenumsurfaces++] = surface;
10278 // render the range of surfaces
10279 if (ent == r_refdef.scene.worldentity)
10280 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10282 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10284 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10287 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10289 // transparent surfaces get pushed off into the transparent queue
10290 int surfacelistindex;
10291 const msurface_t *surface;
10292 vec3_t tempcenter, center;
10293 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10295 surface = texturesurfacelist[surfacelistindex];
10296 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10297 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10298 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10299 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10300 if (queueentity->transparent_offset) // transparent offset
10302 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10303 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10304 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10306 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10310 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10312 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10314 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10316 RSurf_SetupDepthAndCulling();
10317 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10318 if (rsurface.batchvertex3fbuffer)
10319 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10321 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10325 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10327 const entity_render_t *queueentity = r_refdef.scene.worldentity;
10330 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10333 if (!rsurface.texture->currentnumlayers)
10335 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10336 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10338 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10340 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10341 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10342 else if (!rsurface.texture->currentnumlayers)
10344 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10346 // in the deferred case, transparent surfaces were queued during prepass
10347 if (!r_shadow_usingdeferredprepass)
10348 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10352 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10353 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10358 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10361 texture_t *texture;
10362 R_FrameData_SetMark();
10363 // break the surface list down into batches by texture and use of lightmapping
10364 for (i = 0;i < numsurfaces;i = j)
10367 // texture is the base texture pointer, rsurface.texture is the
10368 // current frame/skin the texture is directing us to use (for example
10369 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10370 // use skin 1 instead)
10371 texture = surfacelist[i]->texture;
10372 rsurface.texture = R_GetCurrentTexture(texture);
10373 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10375 // if this texture is not the kind we want, skip ahead to the next one
10376 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10380 if(FAKELIGHT_ENABLED || depthonly || prepass)
10382 rsurface.lightmaptexture = NULL;
10383 rsurface.deluxemaptexture = NULL;
10384 rsurface.uselightmaptexture = false;
10385 // simply scan ahead until we find a different texture or lightmap state
10386 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10391 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10392 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10393 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10394 // simply scan ahead until we find a different texture or lightmap state
10395 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10398 // render the range of surfaces
10399 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10401 R_FrameData_ReturnToMark();
10404 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10408 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10411 if (!rsurface.texture->currentnumlayers)
10413 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10414 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10416 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10418 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10419 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10420 else if (!rsurface.texture->currentnumlayers)
10422 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10424 // in the deferred case, transparent surfaces were queued during prepass
10425 if (!r_shadow_usingdeferredprepass)
10426 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10430 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10431 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10436 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10439 texture_t *texture;
10440 R_FrameData_SetMark();
10441 // break the surface list down into batches by texture and use of lightmapping
10442 for (i = 0;i < numsurfaces;i = j)
10445 // texture is the base texture pointer, rsurface.texture is the
10446 // current frame/skin the texture is directing us to use (for example
10447 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10448 // use skin 1 instead)
10449 texture = surfacelist[i]->texture;
10450 rsurface.texture = R_GetCurrentTexture(texture);
10451 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10453 // if this texture is not the kind we want, skip ahead to the next one
10454 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10458 if(FAKELIGHT_ENABLED || depthonly || prepass)
10460 rsurface.lightmaptexture = NULL;
10461 rsurface.deluxemaptexture = NULL;
10462 rsurface.uselightmaptexture = false;
10463 // simply scan ahead until we find a different texture or lightmap state
10464 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10469 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10470 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10471 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10472 // simply scan ahead until we find a different texture or lightmap state
10473 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10476 // render the range of surfaces
10477 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10479 R_FrameData_ReturnToMark();
10482 float locboxvertex3f[6*4*3] =
10484 1,0,1, 1,0,0, 1,1,0, 1,1,1,
10485 0,1,1, 0,1,0, 0,0,0, 0,0,1,
10486 1,1,1, 1,1,0, 0,1,0, 0,1,1,
10487 0,0,1, 0,0,0, 1,0,0, 1,0,1,
10488 0,0,1, 1,0,1, 1,1,1, 0,1,1,
10489 1,0,0, 0,0,0, 0,1,0, 1,1,0
10492 unsigned short locboxelements[6*2*3] =
10497 12,13,14, 12,14,15,
10498 16,17,18, 16,18,19,
10502 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10505 cl_locnode_t *loc = (cl_locnode_t *)ent;
10507 float vertex3f[6*4*3];
10509 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10510 GL_DepthMask(false);
10511 GL_DepthRange(0, 1);
10512 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10513 GL_DepthTest(true);
10514 GL_CullFace(GL_NONE);
10515 R_EntityMatrix(&identitymatrix);
10517 // R_Mesh_ResetTextureState();
10519 i = surfacelist[0];
10520 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10521 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10522 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10523 surfacelist[0] < 0 ? 0.5f : 0.125f);
10525 if (VectorCompare(loc->mins, loc->maxs))
10527 VectorSet(size, 2, 2, 2);
10528 VectorMA(loc->mins, -0.5f, size, mins);
10532 VectorCopy(loc->mins, mins);
10533 VectorSubtract(loc->maxs, loc->mins, size);
10536 for (i = 0;i < 6*4*3;)
10537 for (j = 0;j < 3;j++, i++)
10538 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10540 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10541 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
10542 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10545 void R_DrawLocs(void)
10548 cl_locnode_t *loc, *nearestloc;
10550 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10551 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10553 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10554 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10558 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10560 if (decalsystem->decals)
10561 Mem_Free(decalsystem->decals);
10562 memset(decalsystem, 0, sizeof(*decalsystem));
10565 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)
10568 tridecal_t *decals;
10571 // expand or initialize the system
10572 if (decalsystem->maxdecals <= decalsystem->numdecals)
10574 decalsystem_t old = *decalsystem;
10575 qboolean useshortelements;
10576 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10577 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10578 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)));
10579 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10580 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10581 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10582 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10583 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10584 if (decalsystem->numdecals)
10585 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10587 Mem_Free(old.decals);
10588 for (i = 0;i < decalsystem->maxdecals*3;i++)
10589 decalsystem->element3i[i] = i;
10590 if (useshortelements)
10591 for (i = 0;i < decalsystem->maxdecals*3;i++)
10592 decalsystem->element3s[i] = i;
10595 // grab a decal and search for another free slot for the next one
10596 decals = decalsystem->decals;
10597 decal = decalsystem->decals + (i = decalsystem->freedecal++);
10598 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10600 decalsystem->freedecal = i;
10601 if (decalsystem->numdecals <= i)
10602 decalsystem->numdecals = i + 1;
10604 // initialize the decal
10606 decal->triangleindex = triangleindex;
10607 decal->surfaceindex = surfaceindex;
10608 decal->decalsequence = decalsequence;
10609 decal->color4f[0][0] = c0[0];
10610 decal->color4f[0][1] = c0[1];
10611 decal->color4f[0][2] = c0[2];
10612 decal->color4f[0][3] = 1;
10613 decal->color4f[1][0] = c1[0];
10614 decal->color4f[1][1] = c1[1];
10615 decal->color4f[1][2] = c1[2];
10616 decal->color4f[1][3] = 1;
10617 decal->color4f[2][0] = c2[0];
10618 decal->color4f[2][1] = c2[1];
10619 decal->color4f[2][2] = c2[2];
10620 decal->color4f[2][3] = 1;
10621 decal->vertex3f[0][0] = v0[0];
10622 decal->vertex3f[0][1] = v0[1];
10623 decal->vertex3f[0][2] = v0[2];
10624 decal->vertex3f[1][0] = v1[0];
10625 decal->vertex3f[1][1] = v1[1];
10626 decal->vertex3f[1][2] = v1[2];
10627 decal->vertex3f[2][0] = v2[0];
10628 decal->vertex3f[2][1] = v2[1];
10629 decal->vertex3f[2][2] = v2[2];
10630 decal->texcoord2f[0][0] = t0[0];
10631 decal->texcoord2f[0][1] = t0[1];
10632 decal->texcoord2f[1][0] = t1[0];
10633 decal->texcoord2f[1][1] = t1[1];
10634 decal->texcoord2f[2][0] = t2[0];
10635 decal->texcoord2f[2][1] = t2[1];
10636 TriangleNormal(v0, v1, v2, decal->plane);
10637 VectorNormalize(decal->plane);
10638 decal->plane[3] = DotProduct(v0, decal->plane);
10641 extern cvar_t cl_decals_bias;
10642 extern cvar_t cl_decals_models;
10643 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10644 // baseparms, parms, temps
10645 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)
10650 const float *vertex3f;
10651 const float *normal3f;
10653 float points[2][9][3];
10660 e = rsurface.modelelement3i + 3*triangleindex;
10662 vertex3f = rsurface.modelvertex3f;
10663 normal3f = rsurface.modelnormal3f;
10667 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10669 index = 3*e[cornerindex];
10670 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10675 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10677 index = 3*e[cornerindex];
10678 VectorCopy(vertex3f + index, v[cornerindex]);
10683 //TriangleNormal(v[0], v[1], v[2], normal);
10684 //if (DotProduct(normal, localnormal) < 0.0f)
10686 // clip by each of the box planes formed from the projection matrix
10687 // if anything survives, we emit the decal
10688 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]);
10691 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]);
10694 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]);
10697 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]);
10700 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]);
10703 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]);
10706 // some part of the triangle survived, so we have to accept it...
10709 // dynamic always uses the original triangle
10711 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10713 index = 3*e[cornerindex];
10714 VectorCopy(vertex3f + index, v[cornerindex]);
10717 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10719 // convert vertex positions to texcoords
10720 Matrix4x4_Transform(projection, v[cornerindex], temp);
10721 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10722 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10723 // calculate distance fade from the projection origin
10724 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10725 f = bound(0.0f, f, 1.0f);
10726 c[cornerindex][0] = r * f;
10727 c[cornerindex][1] = g * f;
10728 c[cornerindex][2] = b * f;
10729 c[cornerindex][3] = 1.0f;
10730 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10733 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);
10735 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10736 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);
10738 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)
10740 matrix4x4_t projection;
10741 decalsystem_t *decalsystem;
10744 const msurface_t *surface;
10745 const msurface_t *surfaces;
10746 const int *surfacelist;
10747 const texture_t *texture;
10749 int numsurfacelist;
10750 int surfacelistindex;
10753 float localorigin[3];
10754 float localnormal[3];
10755 float localmins[3];
10756 float localmaxs[3];
10759 float planes[6][4];
10762 int bih_triangles_count;
10763 int bih_triangles[256];
10764 int bih_surfaces[256];
10766 decalsystem = &ent->decalsystem;
10767 model = ent->model;
10768 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10770 R_DecalSystem_Reset(&ent->decalsystem);
10774 if (!model->brush.data_leafs && !cl_decals_models.integer)
10776 if (decalsystem->model)
10777 R_DecalSystem_Reset(decalsystem);
10781 if (decalsystem->model != model)
10782 R_DecalSystem_Reset(decalsystem);
10783 decalsystem->model = model;
10785 RSurf_ActiveModelEntity(ent, true, false, false);
10787 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10788 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10789 VectorNormalize(localnormal);
10790 localsize = worldsize*rsurface.inversematrixscale;
10791 localmins[0] = localorigin[0] - localsize;
10792 localmins[1] = localorigin[1] - localsize;
10793 localmins[2] = localorigin[2] - localsize;
10794 localmaxs[0] = localorigin[0] + localsize;
10795 localmaxs[1] = localorigin[1] + localsize;
10796 localmaxs[2] = localorigin[2] + localsize;
10798 //VectorCopy(localnormal, planes[4]);
10799 //VectorVectors(planes[4], planes[2], planes[0]);
10800 AnglesFromVectors(angles, localnormal, NULL, false);
10801 AngleVectors(angles, planes[0], planes[2], planes[4]);
10802 VectorNegate(planes[0], planes[1]);
10803 VectorNegate(planes[2], planes[3]);
10804 VectorNegate(planes[4], planes[5]);
10805 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10806 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10807 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10808 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10809 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10810 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10815 matrix4x4_t forwardprojection;
10816 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10817 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10822 float projectionvector[4][3];
10823 VectorScale(planes[0], ilocalsize, projectionvector[0]);
10824 VectorScale(planes[2], ilocalsize, projectionvector[1]);
10825 VectorScale(planes[4], ilocalsize, projectionvector[2]);
10826 projectionvector[0][0] = planes[0][0] * ilocalsize;
10827 projectionvector[0][1] = planes[1][0] * ilocalsize;
10828 projectionvector[0][2] = planes[2][0] * ilocalsize;
10829 projectionvector[1][0] = planes[0][1] * ilocalsize;
10830 projectionvector[1][1] = planes[1][1] * ilocalsize;
10831 projectionvector[1][2] = planes[2][1] * ilocalsize;
10832 projectionvector[2][0] = planes[0][2] * ilocalsize;
10833 projectionvector[2][1] = planes[1][2] * ilocalsize;
10834 projectionvector[2][2] = planes[2][2] * ilocalsize;
10835 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10836 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10837 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10838 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10842 dynamic = model->surfmesh.isanimated;
10843 numsurfacelist = model->nummodelsurfaces;
10844 surfacelist = model->sortedmodelsurfaces;
10845 surfaces = model->data_surfaces;
10848 bih_triangles_count = -1;
10851 if(model->render_bih.numleafs)
10852 bih = &model->render_bih;
10853 else if(model->collision_bih.numleafs)
10854 bih = &model->collision_bih;
10857 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10858 if(bih_triangles_count == 0)
10860 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10862 if(bih_triangles_count > 0)
10864 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10866 surfaceindex = bih_surfaces[triangleindex];
10867 surface = surfaces + surfaceindex;
10868 texture = surface->texture;
10869 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10871 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10873 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10878 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10880 surfaceindex = surfacelist[surfacelistindex];
10881 surface = surfaces + surfaceindex;
10882 // check cull box first because it rejects more than any other check
10883 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10885 // skip transparent surfaces
10886 texture = surface->texture;
10887 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10889 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10891 numtriangles = surface->num_triangles;
10892 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10893 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10898 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10899 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)
10901 int renderentityindex;
10902 float worldmins[3];
10903 float worldmaxs[3];
10904 entity_render_t *ent;
10906 if (!cl_decals_newsystem.integer)
10909 worldmins[0] = worldorigin[0] - worldsize;
10910 worldmins[1] = worldorigin[1] - worldsize;
10911 worldmins[2] = worldorigin[2] - worldsize;
10912 worldmaxs[0] = worldorigin[0] + worldsize;
10913 worldmaxs[1] = worldorigin[1] + worldsize;
10914 worldmaxs[2] = worldorigin[2] + worldsize;
10916 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10918 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10920 ent = r_refdef.scene.entities[renderentityindex];
10921 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10924 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10928 typedef struct r_decalsystem_splatqueue_s
10930 vec3_t worldorigin;
10931 vec3_t worldnormal;
10937 r_decalsystem_splatqueue_t;
10939 int r_decalsystem_numqueued = 0;
10940 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10942 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)
10944 r_decalsystem_splatqueue_t *queue;
10946 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10949 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10950 VectorCopy(worldorigin, queue->worldorigin);
10951 VectorCopy(worldnormal, queue->worldnormal);
10952 Vector4Set(queue->color, r, g, b, a);
10953 Vector4Set(queue->tcrange, s1, t1, s2, t2);
10954 queue->worldsize = worldsize;
10955 queue->decalsequence = cl.decalsequence++;
10958 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10961 r_decalsystem_splatqueue_t *queue;
10963 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10964 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);
10965 r_decalsystem_numqueued = 0;
10968 extern cvar_t cl_decals_max;
10969 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10972 decalsystem_t *decalsystem = &ent->decalsystem;
10979 if (!decalsystem->numdecals)
10982 if (r_showsurfaces.integer)
10985 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10987 R_DecalSystem_Reset(decalsystem);
10991 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10992 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10994 if (decalsystem->lastupdatetime)
10995 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
10998 decalsystem->lastupdatetime = r_refdef.scene.time;
10999 decal = decalsystem->decals;
11000 numdecals = decalsystem->numdecals;
11002 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11004 if (decal->color4f[0][3])
11006 decal->lived += frametime;
11007 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11009 memset(decal, 0, sizeof(*decal));
11010 if (decalsystem->freedecal > i)
11011 decalsystem->freedecal = i;
11015 decal = decalsystem->decals;
11016 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11019 // collapse the array by shuffling the tail decals into the gaps
11022 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11023 decalsystem->freedecal++;
11024 if (decalsystem->freedecal == numdecals)
11026 decal[decalsystem->freedecal] = decal[--numdecals];
11029 decalsystem->numdecals = numdecals;
11031 if (numdecals <= 0)
11033 // if there are no decals left, reset decalsystem
11034 R_DecalSystem_Reset(decalsystem);
11038 extern skinframe_t *decalskinframe;
11039 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11042 decalsystem_t *decalsystem = &ent->decalsystem;
11051 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11054 numdecals = decalsystem->numdecals;
11058 if (r_showsurfaces.integer)
11061 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11063 R_DecalSystem_Reset(decalsystem);
11067 // if the model is static it doesn't matter what value we give for
11068 // wantnormals and wanttangents, so this logic uses only rules applicable
11069 // to a model, knowing that they are meaningless otherwise
11070 if (ent == r_refdef.scene.worldentity)
11071 RSurf_ActiveWorldEntity();
11073 RSurf_ActiveModelEntity(ent, false, false, false);
11075 decalsystem->lastupdatetime = r_refdef.scene.time;
11076 decal = decalsystem->decals;
11078 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11080 // update vertex positions for animated models
11081 v3f = decalsystem->vertex3f;
11082 c4f = decalsystem->color4f;
11083 t2f = decalsystem->texcoord2f;
11084 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11086 if (!decal->color4f[0][3])
11089 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11093 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11096 // update color values for fading decals
11097 if (decal->lived >= cl_decals_time.value)
11098 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11102 c4f[ 0] = decal->color4f[0][0] * alpha;
11103 c4f[ 1] = decal->color4f[0][1] * alpha;
11104 c4f[ 2] = decal->color4f[0][2] * alpha;
11106 c4f[ 4] = decal->color4f[1][0] * alpha;
11107 c4f[ 5] = decal->color4f[1][1] * alpha;
11108 c4f[ 6] = decal->color4f[1][2] * alpha;
11110 c4f[ 8] = decal->color4f[2][0] * alpha;
11111 c4f[ 9] = decal->color4f[2][1] * alpha;
11112 c4f[10] = decal->color4f[2][2] * alpha;
11115 t2f[0] = decal->texcoord2f[0][0];
11116 t2f[1] = decal->texcoord2f[0][1];
11117 t2f[2] = decal->texcoord2f[1][0];
11118 t2f[3] = decal->texcoord2f[1][1];
11119 t2f[4] = decal->texcoord2f[2][0];
11120 t2f[5] = decal->texcoord2f[2][1];
11122 // update vertex positions for animated models
11123 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11125 e = rsurface.modelelement3i + 3*decal->triangleindex;
11126 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11127 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11128 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11132 VectorCopy(decal->vertex3f[0], v3f);
11133 VectorCopy(decal->vertex3f[1], v3f + 3);
11134 VectorCopy(decal->vertex3f[2], v3f + 6);
11137 if (r_refdef.fogenabled)
11139 alpha = RSurf_FogVertex(v3f);
11140 VectorScale(c4f, alpha, c4f);
11141 alpha = RSurf_FogVertex(v3f + 3);
11142 VectorScale(c4f + 4, alpha, c4f + 4);
11143 alpha = RSurf_FogVertex(v3f + 6);
11144 VectorScale(c4f + 8, alpha, c4f + 8);
11155 r_refdef.stats.drawndecals += numtris;
11157 // now render the decals all at once
11158 // (this assumes they all use one particle font texture!)
11159 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);
11160 // R_Mesh_ResetTextureState();
11161 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11162 GL_DepthMask(false);
11163 GL_DepthRange(0, 1);
11164 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11165 GL_DepthTest(true);
11166 GL_CullFace(GL_NONE);
11167 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11168 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false);
11169 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11173 static void R_DrawModelDecals(void)
11177 // fade faster when there are too many decals
11178 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11179 for (i = 0;i < r_refdef.scene.numentities;i++)
11180 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11182 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11183 for (i = 0;i < r_refdef.scene.numentities;i++)
11184 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11185 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11187 R_DecalSystem_ApplySplatEntitiesQueue();
11189 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11190 for (i = 0;i < r_refdef.scene.numentities;i++)
11191 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11193 r_refdef.stats.totaldecals += numdecals;
11195 if (r_showsurfaces.integer)
11198 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11200 for (i = 0;i < r_refdef.scene.numentities;i++)
11202 if (!r_refdef.viewcache.entityvisible[i])
11204 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11205 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11209 extern cvar_t mod_collision_bih;
11210 void R_DrawDebugModel(void)
11212 entity_render_t *ent = rsurface.entity;
11213 int i, j, k, l, flagsmask;
11214 const msurface_t *surface;
11215 dp_model_t *model = ent->model;
11218 if (!sv.active && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11221 if (r_showoverdraw.value > 0)
11223 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11224 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11225 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
11226 GL_DepthTest(false);
11227 GL_DepthMask(false);
11228 GL_DepthRange(0, 1);
11229 GL_BlendFunc(GL_ONE, GL_ONE);
11230 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11232 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11234 rsurface.texture = R_GetCurrentTexture(surface->texture);
11235 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11237 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11238 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11239 if (!rsurface.texture->currentlayers->depthmask)
11240 GL_Color(c, 0, 0, 1.0f);
11241 else if (ent == r_refdef.scene.worldentity)
11242 GL_Color(c, c, c, 1.0f);
11244 GL_Color(0, c, 0, 1.0f);
11245 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11249 rsurface.texture = NULL;
11252 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11254 // R_Mesh_ResetTextureState();
11255 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
11256 GL_DepthRange(0, 1);
11257 GL_DepthTest(!r_showdisabledepthtest.integer);
11258 GL_DepthMask(false);
11259 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11261 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11265 qboolean cullbox = ent == r_refdef.scene.worldentity;
11266 const q3mbrush_t *brush;
11267 const bih_t *bih = &model->collision_bih;
11268 const bih_leaf_t *bihleaf;
11269 float vertex3f[3][3];
11270 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11272 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11274 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11276 switch (bihleaf->type)
11279 brush = model->brush.data_brushes + bihleaf->itemindex;
11280 if (brush->colbrushf && brush->colbrushf->numtriangles)
11282 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);
11283 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11284 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11287 case BIH_COLLISIONTRIANGLE:
11288 triangleindex = bihleaf->itemindex;
11289 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11290 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11291 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11292 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);
11293 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11294 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11296 case BIH_RENDERTRIANGLE:
11297 triangleindex = bihleaf->itemindex;
11298 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11299 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11300 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11301 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);
11302 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11303 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11309 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11311 if (r_showtris.integer && qglPolygonMode)
11313 if (r_showdisabledepthtest.integer)
11315 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11316 GL_DepthMask(false);
11320 GL_BlendFunc(GL_ONE, GL_ZERO);
11321 GL_DepthMask(true);
11323 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11324 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11326 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11328 rsurface.texture = R_GetCurrentTexture(surface->texture);
11329 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11331 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11332 if (!rsurface.texture->currentlayers->depthmask)
11333 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11334 else if (ent == r_refdef.scene.worldentity)
11335 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11337 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11338 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11342 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11343 rsurface.texture = NULL;
11346 if (r_shownormals.value != 0 && qglBegin)
11348 if (r_showdisabledepthtest.integer)
11350 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11351 GL_DepthMask(false);
11355 GL_BlendFunc(GL_ONE, GL_ZERO);
11356 GL_DepthMask(true);
11358 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11360 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11362 rsurface.texture = R_GetCurrentTexture(surface->texture);
11363 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11365 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11366 qglBegin(GL_LINES);
11367 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11369 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11371 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11372 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11373 qglVertex3f(v[0], v[1], v[2]);
11374 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11375 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11376 qglVertex3f(v[0], v[1], v[2]);
11379 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11381 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11383 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11384 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11385 qglVertex3f(v[0], v[1], v[2]);
11386 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11387 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11388 qglVertex3f(v[0], v[1], v[2]);
11391 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11393 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11395 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11396 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11397 qglVertex3f(v[0], v[1], v[2]);
11398 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11399 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11400 qglVertex3f(v[0], v[1], v[2]);
11403 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11405 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11407 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11408 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11409 qglVertex3f(v[0], v[1], v[2]);
11410 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11411 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11412 qglVertex3f(v[0], v[1], v[2]);
11419 rsurface.texture = NULL;
11423 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11424 int r_maxsurfacelist = 0;
11425 const msurface_t **r_surfacelist = NULL;
11426 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11428 int i, j, endj, flagsmask;
11429 dp_model_t *model = r_refdef.scene.worldmodel;
11430 msurface_t *surfaces;
11431 unsigned char *update;
11432 int numsurfacelist = 0;
11436 if (r_maxsurfacelist < model->num_surfaces)
11438 r_maxsurfacelist = model->num_surfaces;
11440 Mem_Free((msurface_t**)r_surfacelist);
11441 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11444 RSurf_ActiveWorldEntity();
11446 surfaces = model->data_surfaces;
11447 update = model->brushq1.lightmapupdateflags;
11449 // update light styles on this submodel
11450 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11452 model_brush_lightstyleinfo_t *style;
11453 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11455 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11457 int *list = style->surfacelist;
11458 style->value = r_refdef.scene.lightstylevalue[style->style];
11459 for (j = 0;j < style->numsurfaces;j++)
11460 update[list[j]] = true;
11465 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11469 R_DrawDebugModel();
11470 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11474 rsurface.lightmaptexture = NULL;
11475 rsurface.deluxemaptexture = NULL;
11476 rsurface.uselightmaptexture = false;
11477 rsurface.texture = NULL;
11478 rsurface.rtlight = NULL;
11479 numsurfacelist = 0;
11480 // add visible surfaces to draw list
11481 for (i = 0;i < model->nummodelsurfaces;i++)
11483 j = model->sortedmodelsurfaces[i];
11484 if (r_refdef.viewcache.world_surfacevisible[j])
11485 r_surfacelist[numsurfacelist++] = surfaces + j;
11487 // update lightmaps if needed
11488 if (model->brushq1.firstrender)
11490 model->brushq1.firstrender = false;
11491 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11493 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11497 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11498 if (r_refdef.viewcache.world_surfacevisible[j])
11500 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11502 // don't do anything if there were no surfaces
11503 if (!numsurfacelist)
11505 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11508 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11510 // add to stats if desired
11511 if (r_speeds.integer && !skysurfaces && !depthonly)
11513 r_refdef.stats.world_surfaces += numsurfacelist;
11514 for (j = 0;j < numsurfacelist;j++)
11515 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11518 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11521 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11523 int i, j, endj, flagsmask;
11524 dp_model_t *model = ent->model;
11525 msurface_t *surfaces;
11526 unsigned char *update;
11527 int numsurfacelist = 0;
11531 if (r_maxsurfacelist < model->num_surfaces)
11533 r_maxsurfacelist = model->num_surfaces;
11535 Mem_Free((msurface_t **)r_surfacelist);
11536 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11539 // if the model is static it doesn't matter what value we give for
11540 // wantnormals and wanttangents, so this logic uses only rules applicable
11541 // to a model, knowing that they are meaningless otherwise
11542 if (ent == r_refdef.scene.worldentity)
11543 RSurf_ActiveWorldEntity();
11544 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11545 RSurf_ActiveModelEntity(ent, false, false, false);
11547 RSurf_ActiveModelEntity(ent, true, true, true);
11548 else if (depthonly)
11550 switch (vid.renderpath)
11552 case RENDERPATH_GL20:
11553 case RENDERPATH_D3D9:
11554 case RENDERPATH_D3D10:
11555 case RENDERPATH_D3D11:
11556 case RENDERPATH_SOFT:
11557 case RENDERPATH_GLES2:
11558 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11560 case RENDERPATH_GL11:
11561 case RENDERPATH_GL13:
11562 case RENDERPATH_GLES1:
11563 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11569 switch (vid.renderpath)
11571 case RENDERPATH_GL20:
11572 case RENDERPATH_D3D9:
11573 case RENDERPATH_D3D10:
11574 case RENDERPATH_D3D11:
11575 case RENDERPATH_SOFT:
11576 case RENDERPATH_GLES2:
11577 RSurf_ActiveModelEntity(ent, true, true, false);
11579 case RENDERPATH_GL11:
11580 case RENDERPATH_GL13:
11581 case RENDERPATH_GLES1:
11582 RSurf_ActiveModelEntity(ent, true, false, false);
11587 surfaces = model->data_surfaces;
11588 update = model->brushq1.lightmapupdateflags;
11590 // update light styles
11591 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11593 model_brush_lightstyleinfo_t *style;
11594 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11596 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11598 int *list = style->surfacelist;
11599 style->value = r_refdef.scene.lightstylevalue[style->style];
11600 for (j = 0;j < style->numsurfaces;j++)
11601 update[list[j]] = true;
11606 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11610 R_DrawDebugModel();
11611 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11615 rsurface.lightmaptexture = NULL;
11616 rsurface.deluxemaptexture = NULL;
11617 rsurface.uselightmaptexture = false;
11618 rsurface.texture = NULL;
11619 rsurface.rtlight = NULL;
11620 numsurfacelist = 0;
11621 // add visible surfaces to draw list
11622 for (i = 0;i < model->nummodelsurfaces;i++)
11623 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11624 // don't do anything if there were no surfaces
11625 if (!numsurfacelist)
11627 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11630 // update lightmaps if needed
11634 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11639 R_BuildLightMap(ent, surfaces + j);
11644 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11646 R_BuildLightMap(ent, surfaces + j);
11647 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11649 // add to stats if desired
11650 if (r_speeds.integer && !skysurfaces && !depthonly)
11652 r_refdef.stats.entities_surfaces += numsurfacelist;
11653 for (j = 0;j < numsurfacelist;j++)
11654 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11657 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11660 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11662 static texture_t texture;
11663 static msurface_t surface;
11664 const msurface_t *surfacelist = &surface;
11666 // fake enough texture and surface state to render this geometry
11668 texture.update_lastrenderframe = -1; // regenerate this texture
11669 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11670 texture.currentskinframe = skinframe;
11671 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11672 texture.offsetmapping = OFFSETMAPPING_OFF;
11673 texture.offsetscale = 1;
11674 texture.specularscalemod = 1;
11675 texture.specularpowermod = 1;
11677 surface.texture = &texture;
11678 surface.num_triangles = numtriangles;
11679 surface.num_firsttriangle = firsttriangle;
11680 surface.num_vertices = numvertices;
11681 surface.num_firstvertex = firstvertex;
11684 rsurface.texture = R_GetCurrentTexture(surface.texture);
11685 rsurface.lightmaptexture = NULL;
11686 rsurface.deluxemaptexture = NULL;
11687 rsurface.uselightmaptexture = false;
11688 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11691 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)
11693 static msurface_t surface;
11694 const msurface_t *surfacelist = &surface;
11696 // fake enough texture and surface state to render this geometry
11697 surface.texture = texture;
11698 surface.num_triangles = numtriangles;
11699 surface.num_firsttriangle = firsttriangle;
11700 surface.num_vertices = numvertices;
11701 surface.num_firstvertex = firstvertex;
11704 rsurface.texture = R_GetCurrentTexture(surface.texture);
11705 rsurface.lightmaptexture = NULL;
11706 rsurface.deluxemaptexture = NULL;
11707 rsurface.uselightmaptexture = false;
11708 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);