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 extern void R_Shadow_UpdateBounceGridTexture(void);
6690 extern cvar_t r_shadow_bouncegrid;
6691 void R_RenderView(void)
6693 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6695 dpsoftrast_test = r_test.integer;
6697 if (r_timereport_active)
6698 R_TimeReport("start");
6699 r_textureframe++; // used only by R_GetCurrentTexture
6700 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6702 if(R_CompileShader_CheckStaticParms())
6705 if (!r_drawentities.integer)
6706 r_refdef.scene.numentities = 0;
6708 R_AnimCache_ClearCache();
6709 R_FrameData_NewFrame();
6711 /* adjust for stereo display */
6712 if(R_Stereo_Active())
6714 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);
6715 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6718 if (r_refdef.view.isoverlay)
6720 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6721 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6722 R_TimeReport("depthclear");
6724 r_refdef.view.showdebug = false;
6726 r_waterstate.enabled = false;
6727 r_waterstate.numwaterplanes = 0;
6731 r_refdef.view.matrix = originalmatrix;
6737 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6739 r_refdef.view.matrix = originalmatrix;
6740 return; //Host_Error ("R_RenderView: NULL worldmodel");
6743 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6745 R_RenderView_UpdateViewVectors();
6747 R_Shadow_UpdateWorldLightSelection();
6749 R_Bloom_StartFrame();
6750 R_Water_StartFrame();
6753 if (r_timereport_active)
6754 R_TimeReport("viewsetup");
6756 R_ResetViewRendering3D();
6758 if (r_refdef.view.clear || r_refdef.fogenabled)
6760 R_ClearScreen(r_refdef.fogenabled);
6761 if (r_timereport_active)
6762 R_TimeReport("viewclear");
6764 r_refdef.view.clear = true;
6766 // this produces a bloom texture to be used in R_BlendView() later
6767 if (r_bloomstate.hdr)
6769 R_HDR_RenderBloomTexture();
6770 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6771 r_textureframe++; // used only by R_GetCurrentTexture
6774 r_refdef.view.showdebug = true;
6777 if (r_timereport_active)
6778 R_TimeReport("visibility");
6780 R_Shadow_UpdateBounceGridTexture();
6781 if (r_timereport_active && r_shadow_bouncegrid.integer)
6782 R_TimeReport("bouncegrid");
6784 r_waterstate.numwaterplanes = 0;
6785 if (r_waterstate.enabled)
6786 R_RenderWaterPlanes();
6789 r_waterstate.numwaterplanes = 0;
6792 if (r_timereport_active)
6793 R_TimeReport("blendview");
6795 GL_Scissor(0, 0, vid.width, vid.height);
6796 GL_ScissorTest(false);
6798 r_refdef.view.matrix = originalmatrix;
6803 void R_RenderWaterPlanes(void)
6805 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6807 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6808 if (r_timereport_active)
6809 R_TimeReport("waterworld");
6812 // don't let sound skip if going slow
6813 if (r_refdef.scene.extraupdate)
6816 R_DrawModelsAddWaterPlanes();
6817 if (r_timereport_active)
6818 R_TimeReport("watermodels");
6820 if (r_waterstate.numwaterplanes)
6822 R_Water_ProcessPlanes();
6823 if (r_timereport_active)
6824 R_TimeReport("waterscenes");
6828 extern void R_DrawLightningBeams (void);
6829 extern void VM_CL_AddPolygonsToMeshQueue (void);
6830 extern void R_DrawPortals (void);
6831 extern cvar_t cl_locs_show;
6832 static void R_DrawLocs(void);
6833 static void R_DrawEntityBBoxes(void);
6834 static void R_DrawModelDecals(void);
6835 extern void R_DrawModelShadows(void);
6836 extern void R_DrawModelShadowMaps(void);
6837 extern cvar_t cl_decals_newsystem;
6838 extern qboolean r_shadow_usingdeferredprepass;
6839 void R_RenderScene(void)
6841 qboolean shadowmapping = false;
6843 if (r_timereport_active)
6844 R_TimeReport("beginscene");
6846 r_refdef.stats.renders++;
6850 // don't let sound skip if going slow
6851 if (r_refdef.scene.extraupdate)
6854 R_MeshQueue_BeginScene();
6858 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);
6860 if (r_timereport_active)
6861 R_TimeReport("skystartframe");
6863 if (cl.csqc_vidvars.drawworld)
6865 // don't let sound skip if going slow
6866 if (r_refdef.scene.extraupdate)
6869 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6871 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6872 if (r_timereport_active)
6873 R_TimeReport("worldsky");
6876 if (R_DrawBrushModelsSky() && r_timereport_active)
6877 R_TimeReport("bmodelsky");
6879 if (skyrendermasked && skyrenderlater)
6881 // we have to force off the water clipping plane while rendering sky
6885 if (r_timereport_active)
6886 R_TimeReport("sky");
6890 R_AnimCache_CacheVisibleEntities();
6891 if (r_timereport_active)
6892 R_TimeReport("animation");
6894 R_Shadow_PrepareLights();
6895 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6896 R_Shadow_PrepareModelShadows();
6897 if (r_timereport_active)
6898 R_TimeReport("preparelights");
6900 if (R_Shadow_ShadowMappingEnabled())
6901 shadowmapping = true;
6903 if (r_shadow_usingdeferredprepass)
6904 R_Shadow_DrawPrepass();
6906 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6908 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6909 if (r_timereport_active)
6910 R_TimeReport("worlddepth");
6912 if (r_depthfirst.integer >= 2)
6914 R_DrawModelsDepth();
6915 if (r_timereport_active)
6916 R_TimeReport("modeldepth");
6919 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6921 R_DrawModelShadowMaps();
6922 R_ResetViewRendering3D();
6923 // don't let sound skip if going slow
6924 if (r_refdef.scene.extraupdate)
6928 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6930 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6931 if (r_timereport_active)
6932 R_TimeReport("world");
6935 // don't let sound skip if going slow
6936 if (r_refdef.scene.extraupdate)
6940 if (r_timereport_active)
6941 R_TimeReport("models");
6943 // don't let sound skip if going slow
6944 if (r_refdef.scene.extraupdate)
6947 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6949 R_DrawModelShadows();
6950 R_ResetViewRendering3D();
6951 // don't let sound skip if going slow
6952 if (r_refdef.scene.extraupdate)
6956 if (!r_shadow_usingdeferredprepass)
6958 R_Shadow_DrawLights();
6959 if (r_timereport_active)
6960 R_TimeReport("rtlights");
6963 // don't let sound skip if going slow
6964 if (r_refdef.scene.extraupdate)
6967 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6969 R_DrawModelShadows();
6970 R_ResetViewRendering3D();
6971 // don't let sound skip if going slow
6972 if (r_refdef.scene.extraupdate)
6976 if (cl.csqc_vidvars.drawworld)
6978 if (cl_decals_newsystem.integer)
6980 R_DrawModelDecals();
6981 if (r_timereport_active)
6982 R_TimeReport("modeldecals");
6987 if (r_timereport_active)
6988 R_TimeReport("decals");
6992 if (r_timereport_active)
6993 R_TimeReport("particles");
6996 if (r_timereport_active)
6997 R_TimeReport("explosions");
6999 R_DrawLightningBeams();
7000 if (r_timereport_active)
7001 R_TimeReport("lightning");
7004 VM_CL_AddPolygonsToMeshQueue();
7006 if (r_refdef.view.showdebug)
7008 if (cl_locs_show.integer)
7011 if (r_timereport_active)
7012 R_TimeReport("showlocs");
7015 if (r_drawportals.integer)
7018 if (r_timereport_active)
7019 R_TimeReport("portals");
7022 if (r_showbboxes.value > 0)
7024 R_DrawEntityBBoxes();
7025 if (r_timereport_active)
7026 R_TimeReport("bboxes");
7030 if (r_transparent.integer)
7032 R_MeshQueue_RenderTransparent();
7033 if (r_timereport_active)
7034 R_TimeReport("drawtrans");
7037 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))
7039 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7040 if (r_timereport_active)
7041 R_TimeReport("worlddebug");
7042 R_DrawModelsDebug();
7043 if (r_timereport_active)
7044 R_TimeReport("modeldebug");
7047 if (cl.csqc_vidvars.drawworld)
7049 R_Shadow_DrawCoronas();
7050 if (r_timereport_active)
7051 R_TimeReport("coronas");
7056 GL_DepthTest(false);
7057 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7058 GL_Color(1, 1, 1, 1);
7059 qglBegin(GL_POLYGON);
7060 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7061 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7062 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7063 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7065 qglBegin(GL_POLYGON);
7066 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]);
7067 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]);
7068 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]);
7069 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]);
7071 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7075 // don't let sound skip if going slow
7076 if (r_refdef.scene.extraupdate)
7079 R_ResetViewRendering2D();
7082 static const unsigned short bboxelements[36] =
7092 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7095 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7097 RSurf_ActiveWorldEntity();
7099 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7100 GL_DepthMask(false);
7101 GL_DepthRange(0, 1);
7102 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7103 // R_Mesh_ResetTextureState();
7105 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7106 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7107 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7108 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7109 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7110 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7111 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7112 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7113 R_FillColors(color4f, 8, cr, cg, cb, ca);
7114 if (r_refdef.fogenabled)
7116 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7118 f1 = RSurf_FogVertex(v);
7120 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7121 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7122 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7125 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7126 R_Mesh_ResetTextureState();
7127 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
7128 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7131 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7135 prvm_edict_t *edict;
7136 prvm_prog_t *prog_save = prog;
7138 // this function draws bounding boxes of server entities
7142 GL_CullFace(GL_NONE);
7143 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
7147 for (i = 0;i < numsurfaces;i++)
7149 edict = PRVM_EDICT_NUM(surfacelist[i]);
7150 switch ((int)PRVM_serveredictfloat(edict, solid))
7152 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
7153 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
7154 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
7155 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7156 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
7157 default: Vector4Set(color, 0, 0, 0, 0.50);break;
7159 color[3] *= r_showbboxes.value;
7160 color[3] = bound(0, color[3], 1);
7161 GL_DepthTest(!r_showdisabledepthtest.integer);
7162 GL_CullFace(r_refdef.view.cullface_front);
7163 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7169 static void R_DrawEntityBBoxes(void)
7172 prvm_edict_t *edict;
7174 prvm_prog_t *prog_save = prog;
7176 // this function draws bounding boxes of server entities
7182 for (i = 0;i < prog->num_edicts;i++)
7184 edict = PRVM_EDICT_NUM(i);
7185 if (edict->priv.server->free)
7187 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7188 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7190 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7192 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7193 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7199 static const int nomodelelement3i[24] =
7211 static const unsigned short nomodelelement3s[24] =
7223 static const float nomodelvertex3f[6*3] =
7233 static const float nomodelcolor4f[6*4] =
7235 0.0f, 0.0f, 0.5f, 1.0f,
7236 0.0f, 0.0f, 0.5f, 1.0f,
7237 0.0f, 0.5f, 0.0f, 1.0f,
7238 0.0f, 0.5f, 0.0f, 1.0f,
7239 0.5f, 0.0f, 0.0f, 1.0f,
7240 0.5f, 0.0f, 0.0f, 1.0f
7243 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7249 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);
7251 // this is only called once per entity so numsurfaces is always 1, and
7252 // surfacelist is always {0}, so this code does not handle batches
7254 if (rsurface.ent_flags & RENDER_ADDITIVE)
7256 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7257 GL_DepthMask(false);
7259 else if (rsurface.colormod[3] < 1)
7261 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7262 GL_DepthMask(false);
7266 GL_BlendFunc(GL_ONE, GL_ZERO);
7269 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7270 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7271 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7272 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7273 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7274 for (i = 0, c = color4f;i < 6;i++, c += 4)
7276 c[0] *= rsurface.colormod[0];
7277 c[1] *= rsurface.colormod[1];
7278 c[2] *= rsurface.colormod[2];
7279 c[3] *= rsurface.colormod[3];
7281 if (r_refdef.fogenabled)
7283 for (i = 0, c = color4f;i < 6;i++, c += 4)
7285 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7287 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7288 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7289 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7292 // R_Mesh_ResetTextureState();
7293 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
7294 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7295 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7298 void R_DrawNoModel(entity_render_t *ent)
7301 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7302 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7303 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7305 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7308 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7310 vec3_t right1, right2, diff, normal;
7312 VectorSubtract (org2, org1, normal);
7314 // calculate 'right' vector for start
7315 VectorSubtract (r_refdef.view.origin, org1, diff);
7316 CrossProduct (normal, diff, right1);
7317 VectorNormalize (right1);
7319 // calculate 'right' vector for end
7320 VectorSubtract (r_refdef.view.origin, org2, diff);
7321 CrossProduct (normal, diff, right2);
7322 VectorNormalize (right2);
7324 vert[ 0] = org1[0] + width * right1[0];
7325 vert[ 1] = org1[1] + width * right1[1];
7326 vert[ 2] = org1[2] + width * right1[2];
7327 vert[ 3] = org1[0] - width * right1[0];
7328 vert[ 4] = org1[1] - width * right1[1];
7329 vert[ 5] = org1[2] - width * right1[2];
7330 vert[ 6] = org2[0] - width * right2[0];
7331 vert[ 7] = org2[1] - width * right2[1];
7332 vert[ 8] = org2[2] - width * right2[2];
7333 vert[ 9] = org2[0] + width * right2[0];
7334 vert[10] = org2[1] + width * right2[1];
7335 vert[11] = org2[2] + width * right2[2];
7338 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)
7340 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7341 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7342 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7343 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7344 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7345 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7346 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7347 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7348 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7349 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7350 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7351 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7354 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7359 VectorSet(v, x, y, z);
7360 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7361 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7363 if (i == mesh->numvertices)
7365 if (mesh->numvertices < mesh->maxvertices)
7367 VectorCopy(v, vertex3f);
7368 mesh->numvertices++;
7370 return mesh->numvertices;
7376 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7380 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7381 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7382 e = mesh->element3i + mesh->numtriangles * 3;
7383 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7385 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7386 if (mesh->numtriangles < mesh->maxtriangles)
7391 mesh->numtriangles++;
7393 element[1] = element[2];
7397 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7401 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7402 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7403 e = mesh->element3i + mesh->numtriangles * 3;
7404 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7406 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7407 if (mesh->numtriangles < mesh->maxtriangles)
7412 mesh->numtriangles++;
7414 element[1] = element[2];
7418 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7419 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7421 int planenum, planenum2;
7424 mplane_t *plane, *plane2;
7426 double temppoints[2][256*3];
7427 // figure out how large a bounding box we need to properly compute this brush
7429 for (w = 0;w < numplanes;w++)
7430 maxdist = max(maxdist, fabs(planes[w].dist));
7431 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7432 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7433 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7437 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7438 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7440 if (planenum2 == planenum)
7442 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);
7445 if (tempnumpoints < 3)
7447 // generate elements forming a triangle fan for this polygon
7448 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7452 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)
7454 texturelayer_t *layer;
7455 layer = t->currentlayers + t->currentnumlayers++;
7457 layer->depthmask = depthmask;
7458 layer->blendfunc1 = blendfunc1;
7459 layer->blendfunc2 = blendfunc2;
7460 layer->texture = texture;
7461 layer->texmatrix = *matrix;
7462 layer->color[0] = r;
7463 layer->color[1] = g;
7464 layer->color[2] = b;
7465 layer->color[3] = a;
7468 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7470 if(parms[0] == 0 && parms[1] == 0)
7472 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7473 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7478 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7481 index = parms[2] + rsurface.shadertime * parms[3];
7482 index -= floor(index);
7483 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7486 case Q3WAVEFUNC_NONE:
7487 case Q3WAVEFUNC_NOISE:
7488 case Q3WAVEFUNC_COUNT:
7491 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7492 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7493 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7494 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7495 case Q3WAVEFUNC_TRIANGLE:
7497 f = index - floor(index);
7510 f = parms[0] + parms[1] * f;
7511 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7512 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7516 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7522 matrix4x4_t matrix, temp;
7523 switch(tcmod->tcmod)
7527 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7528 matrix = r_waterscrollmatrix;
7530 matrix = identitymatrix;
7532 case Q3TCMOD_ENTITYTRANSLATE:
7533 // this is used in Q3 to allow the gamecode to control texcoord
7534 // scrolling on the entity, which is not supported in darkplaces yet.
7535 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7537 case Q3TCMOD_ROTATE:
7538 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7539 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
7540 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7543 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7545 case Q3TCMOD_SCROLL:
7546 // extra care is needed because of precision breakdown with large values of time
7547 offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7548 offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7549 Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7551 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7552 w = (int) tcmod->parms[0];
7553 h = (int) tcmod->parms[1];
7554 f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7556 idx = (int) floor(f * w * h);
7557 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7559 case Q3TCMOD_STRETCH:
7560 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7561 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7563 case Q3TCMOD_TRANSFORM:
7564 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
7565 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
7566 VectorSet(tcmat + 6, 0 , 0 , 1);
7567 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
7568 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7570 case Q3TCMOD_TURBULENT:
7571 // this is handled in the RSurf_PrepareVertices function
7572 matrix = identitymatrix;
7576 Matrix4x4_Concat(texmatrix, &matrix, &temp);
7579 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7581 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7582 char name[MAX_QPATH];
7583 skinframe_t *skinframe;
7584 unsigned char pixels[296*194];
7585 strlcpy(cache->name, skinname, sizeof(cache->name));
7586 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7587 if (developer_loading.integer)
7588 Con_Printf("loading %s\n", name);
7589 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7590 if (!skinframe || !skinframe->base)
7593 fs_offset_t filesize;
7595 f = FS_LoadFile(name, tempmempool, true, &filesize);
7598 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7599 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7603 cache->skinframe = skinframe;
7606 texture_t *R_GetCurrentTexture(texture_t *t)
7609 const entity_render_t *ent = rsurface.entity;
7610 dp_model_t *model = ent->model;
7611 q3shaderinfo_layer_tcmod_t *tcmod;
7613 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7614 return t->currentframe;
7615 t->update_lastrenderframe = r_textureframe;
7616 t->update_lastrenderentity = (void *)ent;
7618 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7619 t->camera_entity = ent->entitynumber;
7621 t->camera_entity = 0;
7623 // switch to an alternate material if this is a q1bsp animated material
7625 texture_t *texture = t;
7626 int s = rsurface.ent_skinnum;
7627 if ((unsigned int)s >= (unsigned int)model->numskins)
7629 if (model->skinscenes)
7631 if (model->skinscenes[s].framecount > 1)
7632 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7634 s = model->skinscenes[s].firstframe;
7637 t = t + s * model->num_surfaces;
7640 // use an alternate animation if the entity's frame is not 0,
7641 // and only if the texture has an alternate animation
7642 if (rsurface.ent_alttextures && t->anim_total[1])
7643 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7645 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7647 texture->currentframe = t;
7650 // update currentskinframe to be a qw skin or animation frame
7651 if (rsurface.ent_qwskin >= 0)
7653 i = rsurface.ent_qwskin;
7654 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7656 r_qwskincache_size = cl.maxclients;
7658 Mem_Free(r_qwskincache);
7659 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7661 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7662 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7663 t->currentskinframe = r_qwskincache[i].skinframe;
7664 if (t->currentskinframe == NULL)
7665 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7667 else if (t->numskinframes >= 2)
7668 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7669 if (t->backgroundnumskinframes >= 2)
7670 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7672 t->currentmaterialflags = t->basematerialflags;
7673 t->currentalpha = rsurface.colormod[3];
7674 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7675 t->currentalpha *= r_wateralpha.value;
7676 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7677 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7678 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7679 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7680 if (!(rsurface.ent_flags & RENDER_LIGHT))
7681 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7682 else if (FAKELIGHT_ENABLED)
7684 // no modellight if using fakelight for the map
7686 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7688 // pick a model lighting mode
7689 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7690 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7692 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7694 if (rsurface.ent_flags & RENDER_ADDITIVE)
7695 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7696 else if (t->currentalpha < 1)
7697 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7698 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7699 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7700 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7701 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7702 if (t->backgroundnumskinframes)
7703 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7704 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7706 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7707 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7710 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7711 if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
7713 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
7714 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
7716 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7717 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7719 // there is no tcmod
7720 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7722 t->currenttexmatrix = r_waterscrollmatrix;
7723 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7725 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7727 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7728 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7731 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7732 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7733 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7734 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7736 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7737 if (t->currentskinframe->qpixels)
7738 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7739 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7740 if (!t->basetexture)
7741 t->basetexture = r_texture_notexture;
7742 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7743 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7744 t->nmaptexture = t->currentskinframe->nmap;
7745 if (!t->nmaptexture)
7746 t->nmaptexture = r_texture_blanknormalmap;
7747 t->glosstexture = r_texture_black;
7748 t->glowtexture = t->currentskinframe->glow;
7749 t->fogtexture = t->currentskinframe->fog;
7750 t->reflectmasktexture = t->currentskinframe->reflect;
7751 if (t->backgroundnumskinframes)
7753 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7754 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7755 t->backgroundglosstexture = r_texture_black;
7756 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7757 if (!t->backgroundnmaptexture)
7758 t->backgroundnmaptexture = r_texture_blanknormalmap;
7762 t->backgroundbasetexture = r_texture_white;
7763 t->backgroundnmaptexture = r_texture_blanknormalmap;
7764 t->backgroundglosstexture = r_texture_black;
7765 t->backgroundglowtexture = NULL;
7767 t->specularpower = r_shadow_glossexponent.value;
7768 // TODO: store reference values for these in the texture?
7769 t->specularscale = 0;
7770 if (r_shadow_gloss.integer > 0)
7772 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7774 if (r_shadow_glossintensity.value > 0)
7776 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7777 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7778 t->specularscale = r_shadow_glossintensity.value;
7781 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7783 t->glosstexture = r_texture_white;
7784 t->backgroundglosstexture = r_texture_white;
7785 t->specularscale = r_shadow_gloss2intensity.value;
7786 t->specularpower = r_shadow_gloss2exponent.value;
7789 t->specularscale *= t->specularscalemod;
7790 t->specularpower *= t->specularpowermod;
7792 // lightmaps mode looks bad with dlights using actual texturing, so turn
7793 // off the colormap and glossmap, but leave the normalmap on as it still
7794 // accurately represents the shading involved
7795 if (gl_lightmaps.integer)
7797 t->basetexture = r_texture_grey128;
7798 t->pantstexture = r_texture_black;
7799 t->shirttexture = r_texture_black;
7800 t->nmaptexture = r_texture_blanknormalmap;
7801 t->glosstexture = r_texture_black;
7802 t->glowtexture = NULL;
7803 t->fogtexture = NULL;
7804 t->reflectmasktexture = NULL;
7805 t->backgroundbasetexture = NULL;
7806 t->backgroundnmaptexture = r_texture_blanknormalmap;
7807 t->backgroundglosstexture = r_texture_black;
7808 t->backgroundglowtexture = NULL;
7809 t->specularscale = 0;
7810 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7813 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7814 VectorClear(t->dlightcolor);
7815 t->currentnumlayers = 0;
7816 if (t->currentmaterialflags & MATERIALFLAG_WALL)
7818 int blendfunc1, blendfunc2;
7820 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7822 blendfunc1 = GL_SRC_ALPHA;
7823 blendfunc2 = GL_ONE;
7825 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7827 blendfunc1 = GL_SRC_ALPHA;
7828 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7830 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7832 blendfunc1 = t->customblendfunc[0];
7833 blendfunc2 = t->customblendfunc[1];
7837 blendfunc1 = GL_ONE;
7838 blendfunc2 = GL_ZERO;
7840 // don't colormod evilblend textures
7841 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7842 VectorSet(t->lightmapcolor, 1, 1, 1);
7843 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7844 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7846 // fullbright is not affected by r_refdef.lightmapintensity
7847 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]);
7848 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7849 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]);
7850 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7851 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]);
7855 vec3_t ambientcolor;
7857 // set the color tint used for lights affecting this surface
7858 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7860 // q3bsp has no lightmap updates, so the lightstylevalue that
7861 // would normally be baked into the lightmap must be
7862 // applied to the color
7863 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7864 if (model->type == mod_brushq3)
7865 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7866 colorscale *= r_refdef.lightmapintensity;
7867 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7868 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7869 // basic lit geometry
7870 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]);
7871 // add pants/shirt if needed
7872 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7873 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]);
7874 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7875 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]);
7876 // now add ambient passes if needed
7877 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7879 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]);
7880 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7881 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]);
7882 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7883 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]);
7886 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7887 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]);
7888 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7890 // if this is opaque use alpha blend which will darken the earlier
7893 // if this is an alpha blended material, all the earlier passes
7894 // were darkened by fog already, so we only need to add the fog
7895 // color ontop through the fog mask texture
7897 // if this is an additive blended material, all the earlier passes
7898 // were darkened by fog already, and we should not add fog color
7899 // (because the background was not darkened, there is no fog color
7900 // that was lost behind it).
7901 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]);
7905 return t->currentframe;
7908 rsurfacestate_t rsurface;
7910 void RSurf_ActiveWorldEntity(void)
7912 dp_model_t *model = r_refdef.scene.worldmodel;
7913 //if (rsurface.entity == r_refdef.scene.worldentity)
7915 rsurface.entity = r_refdef.scene.worldentity;
7916 rsurface.skeleton = NULL;
7917 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7918 rsurface.ent_skinnum = 0;
7919 rsurface.ent_qwskin = -1;
7920 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7921 rsurface.shadertime = r_refdef.scene.time;
7922 rsurface.matrix = identitymatrix;
7923 rsurface.inversematrix = identitymatrix;
7924 rsurface.matrixscale = 1;
7925 rsurface.inversematrixscale = 1;
7926 R_EntityMatrix(&identitymatrix);
7927 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7928 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7929 rsurface.fograngerecip = r_refdef.fograngerecip;
7930 rsurface.fogheightfade = r_refdef.fogheightfade;
7931 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7932 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7933 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7934 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7935 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7936 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7937 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7938 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7939 rsurface.colormod[3] = 1;
7940 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);
7941 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7942 rsurface.frameblend[0].lerp = 1;
7943 rsurface.ent_alttextures = false;
7944 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7945 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7946 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7947 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7948 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7949 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7950 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7951 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7952 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7953 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7954 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7955 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7956 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7957 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7958 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7959 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7960 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7961 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7962 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7963 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7964 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7965 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7966 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7967 rsurface.modelelement3i = model->surfmesh.data_element3i;
7968 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7969 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7970 rsurface.modelelement3s = model->surfmesh.data_element3s;
7971 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7972 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7973 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7974 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7975 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7976 rsurface.modelsurfaces = model->data_surfaces;
7977 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7978 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7979 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7980 rsurface.modelgeneratedvertex = false;
7981 rsurface.batchgeneratedvertex = false;
7982 rsurface.batchfirstvertex = 0;
7983 rsurface.batchnumvertices = 0;
7984 rsurface.batchfirsttriangle = 0;
7985 rsurface.batchnumtriangles = 0;
7986 rsurface.batchvertex3f = NULL;
7987 rsurface.batchvertex3f_vertexbuffer = NULL;
7988 rsurface.batchvertex3f_bufferoffset = 0;
7989 rsurface.batchsvector3f = NULL;
7990 rsurface.batchsvector3f_vertexbuffer = NULL;
7991 rsurface.batchsvector3f_bufferoffset = 0;
7992 rsurface.batchtvector3f = NULL;
7993 rsurface.batchtvector3f_vertexbuffer = NULL;
7994 rsurface.batchtvector3f_bufferoffset = 0;
7995 rsurface.batchnormal3f = NULL;
7996 rsurface.batchnormal3f_vertexbuffer = NULL;
7997 rsurface.batchnormal3f_bufferoffset = 0;
7998 rsurface.batchlightmapcolor4f = NULL;
7999 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8000 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8001 rsurface.batchtexcoordtexture2f = NULL;
8002 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8003 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8004 rsurface.batchtexcoordlightmap2f = NULL;
8005 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8006 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8007 rsurface.batchvertexmesh = NULL;
8008 rsurface.batchvertexmeshbuffer = NULL;
8009 rsurface.batchvertex3fbuffer = NULL;
8010 rsurface.batchelement3i = NULL;
8011 rsurface.batchelement3i_indexbuffer = NULL;
8012 rsurface.batchelement3i_bufferoffset = 0;
8013 rsurface.batchelement3s = NULL;
8014 rsurface.batchelement3s_indexbuffer = NULL;
8015 rsurface.batchelement3s_bufferoffset = 0;
8016 rsurface.passcolor4f = NULL;
8017 rsurface.passcolor4f_vertexbuffer = NULL;
8018 rsurface.passcolor4f_bufferoffset = 0;
8021 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8023 dp_model_t *model = ent->model;
8024 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8026 rsurface.entity = (entity_render_t *)ent;
8027 rsurface.skeleton = ent->skeleton;
8028 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8029 rsurface.ent_skinnum = ent->skinnum;
8030 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;
8031 rsurface.ent_flags = ent->flags;
8032 rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8033 rsurface.matrix = ent->matrix;
8034 rsurface.inversematrix = ent->inversematrix;
8035 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8036 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8037 R_EntityMatrix(&rsurface.matrix);
8038 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8039 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8040 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8041 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8042 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8043 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8044 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8045 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8046 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8047 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8048 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8049 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8050 rsurface.colormod[3] = ent->alpha;
8051 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8052 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8053 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8054 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8055 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8056 if (ent->model->brush.submodel && !prepass)
8058 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8059 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8061 if (model->surfmesh.isanimated && model->AnimateVertices)
8063 if (ent->animcache_vertex3f)
8065 rsurface.modelvertex3f = ent->animcache_vertex3f;
8066 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8067 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8068 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8069 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8070 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8071 rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8073 else if (wanttangents)
8075 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8076 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8077 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8078 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8079 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8080 rsurface.modelvertexmesh = NULL;
8081 rsurface.modelvertexmeshbuffer = NULL;
8082 rsurface.modelvertex3fbuffer = NULL;
8084 else if (wantnormals)
8086 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8087 rsurface.modelsvector3f = NULL;
8088 rsurface.modeltvector3f = NULL;
8089 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8090 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8091 rsurface.modelvertexmesh = NULL;
8092 rsurface.modelvertexmeshbuffer = NULL;
8093 rsurface.modelvertex3fbuffer = NULL;
8097 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8098 rsurface.modelsvector3f = NULL;
8099 rsurface.modeltvector3f = NULL;
8100 rsurface.modelnormal3f = NULL;
8101 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8102 rsurface.modelvertexmesh = NULL;
8103 rsurface.modelvertexmeshbuffer = NULL;
8104 rsurface.modelvertex3fbuffer = NULL;
8106 rsurface.modelvertex3f_vertexbuffer = 0;
8107 rsurface.modelvertex3f_bufferoffset = 0;
8108 rsurface.modelsvector3f_vertexbuffer = 0;
8109 rsurface.modelsvector3f_bufferoffset = 0;
8110 rsurface.modeltvector3f_vertexbuffer = 0;
8111 rsurface.modeltvector3f_bufferoffset = 0;
8112 rsurface.modelnormal3f_vertexbuffer = 0;
8113 rsurface.modelnormal3f_bufferoffset = 0;
8114 rsurface.modelgeneratedvertex = true;
8118 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8119 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8120 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8121 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8122 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8123 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8124 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8125 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8126 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8127 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8128 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8129 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8130 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8131 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8132 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8133 rsurface.modelgeneratedvertex = false;
8135 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8136 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8137 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8138 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8139 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8140 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8141 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8142 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8143 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8144 rsurface.modelelement3i = model->surfmesh.data_element3i;
8145 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8146 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8147 rsurface.modelelement3s = model->surfmesh.data_element3s;
8148 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8149 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8150 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8151 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8152 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8153 rsurface.modelsurfaces = model->data_surfaces;
8154 rsurface.batchgeneratedvertex = false;
8155 rsurface.batchfirstvertex = 0;
8156 rsurface.batchnumvertices = 0;
8157 rsurface.batchfirsttriangle = 0;
8158 rsurface.batchnumtriangles = 0;
8159 rsurface.batchvertex3f = NULL;
8160 rsurface.batchvertex3f_vertexbuffer = NULL;
8161 rsurface.batchvertex3f_bufferoffset = 0;
8162 rsurface.batchsvector3f = NULL;
8163 rsurface.batchsvector3f_vertexbuffer = NULL;
8164 rsurface.batchsvector3f_bufferoffset = 0;
8165 rsurface.batchtvector3f = NULL;
8166 rsurface.batchtvector3f_vertexbuffer = NULL;
8167 rsurface.batchtvector3f_bufferoffset = 0;
8168 rsurface.batchnormal3f = NULL;
8169 rsurface.batchnormal3f_vertexbuffer = NULL;
8170 rsurface.batchnormal3f_bufferoffset = 0;
8171 rsurface.batchlightmapcolor4f = NULL;
8172 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8173 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8174 rsurface.batchtexcoordtexture2f = NULL;
8175 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8176 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8177 rsurface.batchtexcoordlightmap2f = NULL;
8178 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8179 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8180 rsurface.batchvertexmesh = NULL;
8181 rsurface.batchvertexmeshbuffer = NULL;
8182 rsurface.batchvertex3fbuffer = NULL;
8183 rsurface.batchelement3i = NULL;
8184 rsurface.batchelement3i_indexbuffer = NULL;
8185 rsurface.batchelement3i_bufferoffset = 0;
8186 rsurface.batchelement3s = NULL;
8187 rsurface.batchelement3s_indexbuffer = NULL;
8188 rsurface.batchelement3s_bufferoffset = 0;
8189 rsurface.passcolor4f = NULL;
8190 rsurface.passcolor4f_vertexbuffer = NULL;
8191 rsurface.passcolor4f_bufferoffset = 0;
8194 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)
8196 rsurface.entity = r_refdef.scene.worldentity;
8197 rsurface.skeleton = NULL;
8198 rsurface.ent_skinnum = 0;
8199 rsurface.ent_qwskin = -1;
8200 rsurface.ent_flags = entflags;
8201 rsurface.shadertime = r_refdef.scene.time - shadertime;
8202 rsurface.modelnumvertices = numvertices;
8203 rsurface.modelnumtriangles = numtriangles;
8204 rsurface.matrix = *matrix;
8205 rsurface.inversematrix = *inversematrix;
8206 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8207 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8208 R_EntityMatrix(&rsurface.matrix);
8209 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8210 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8211 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8212 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8213 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8214 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8215 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8216 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8217 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8218 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8219 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8220 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8221 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);
8222 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8223 rsurface.frameblend[0].lerp = 1;
8224 rsurface.ent_alttextures = false;
8225 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8226 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8229 rsurface.modelvertex3f = (float *)vertex3f;
8230 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8231 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8232 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8234 else if (wantnormals)
8236 rsurface.modelvertex3f = (float *)vertex3f;
8237 rsurface.modelsvector3f = NULL;
8238 rsurface.modeltvector3f = NULL;
8239 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8243 rsurface.modelvertex3f = (float *)vertex3f;
8244 rsurface.modelsvector3f = NULL;
8245 rsurface.modeltvector3f = NULL;
8246 rsurface.modelnormal3f = NULL;
8248 rsurface.modelvertexmesh = NULL;
8249 rsurface.modelvertexmeshbuffer = NULL;
8250 rsurface.modelvertex3fbuffer = NULL;
8251 rsurface.modelvertex3f_vertexbuffer = 0;
8252 rsurface.modelvertex3f_bufferoffset = 0;
8253 rsurface.modelsvector3f_vertexbuffer = 0;
8254 rsurface.modelsvector3f_bufferoffset = 0;
8255 rsurface.modeltvector3f_vertexbuffer = 0;
8256 rsurface.modeltvector3f_bufferoffset = 0;
8257 rsurface.modelnormal3f_vertexbuffer = 0;
8258 rsurface.modelnormal3f_bufferoffset = 0;
8259 rsurface.modelgeneratedvertex = true;
8260 rsurface.modellightmapcolor4f = (float *)color4f;
8261 rsurface.modellightmapcolor4f_vertexbuffer = 0;
8262 rsurface.modellightmapcolor4f_bufferoffset = 0;
8263 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
8264 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8265 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8266 rsurface.modeltexcoordlightmap2f = NULL;
8267 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8268 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8269 rsurface.modelelement3i = (int *)element3i;
8270 rsurface.modelelement3i_indexbuffer = NULL;
8271 rsurface.modelelement3i_bufferoffset = 0;
8272 rsurface.modelelement3s = (unsigned short *)element3s;
8273 rsurface.modelelement3s_indexbuffer = NULL;
8274 rsurface.modelelement3s_bufferoffset = 0;
8275 rsurface.modellightmapoffsets = NULL;
8276 rsurface.modelsurfaces = NULL;
8277 rsurface.batchgeneratedvertex = false;
8278 rsurface.batchfirstvertex = 0;
8279 rsurface.batchnumvertices = 0;
8280 rsurface.batchfirsttriangle = 0;
8281 rsurface.batchnumtriangles = 0;
8282 rsurface.batchvertex3f = NULL;
8283 rsurface.batchvertex3f_vertexbuffer = NULL;
8284 rsurface.batchvertex3f_bufferoffset = 0;
8285 rsurface.batchsvector3f = NULL;
8286 rsurface.batchsvector3f_vertexbuffer = NULL;
8287 rsurface.batchsvector3f_bufferoffset = 0;
8288 rsurface.batchtvector3f = NULL;
8289 rsurface.batchtvector3f_vertexbuffer = NULL;
8290 rsurface.batchtvector3f_bufferoffset = 0;
8291 rsurface.batchnormal3f = NULL;
8292 rsurface.batchnormal3f_vertexbuffer = NULL;
8293 rsurface.batchnormal3f_bufferoffset = 0;
8294 rsurface.batchlightmapcolor4f = NULL;
8295 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8296 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8297 rsurface.batchtexcoordtexture2f = NULL;
8298 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8299 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8300 rsurface.batchtexcoordlightmap2f = NULL;
8301 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8302 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8303 rsurface.batchvertexmesh = NULL;
8304 rsurface.batchvertexmeshbuffer = NULL;
8305 rsurface.batchvertex3fbuffer = NULL;
8306 rsurface.batchelement3i = NULL;
8307 rsurface.batchelement3i_indexbuffer = NULL;
8308 rsurface.batchelement3i_bufferoffset = 0;
8309 rsurface.batchelement3s = NULL;
8310 rsurface.batchelement3s_indexbuffer = NULL;
8311 rsurface.batchelement3s_bufferoffset = 0;
8312 rsurface.passcolor4f = NULL;
8313 rsurface.passcolor4f_vertexbuffer = NULL;
8314 rsurface.passcolor4f_bufferoffset = 0;
8316 if (rsurface.modelnumvertices && rsurface.modelelement3i)
8318 if ((wantnormals || wanttangents) && !normal3f)
8320 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8321 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8323 if (wanttangents && !svector3f)
8325 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8326 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8327 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8332 float RSurf_FogPoint(const float *v)
8334 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8335 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8336 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8337 float FogHeightFade = r_refdef.fogheightfade;
8339 unsigned int fogmasktableindex;
8340 if (r_refdef.fogplaneviewabove)
8341 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8343 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8344 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8345 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8348 float RSurf_FogVertex(const float *v)
8350 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8351 float FogPlaneViewDist = rsurface.fogplaneviewdist;
8352 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8353 float FogHeightFade = rsurface.fogheightfade;
8355 unsigned int fogmasktableindex;
8356 if (r_refdef.fogplaneviewabove)
8357 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8359 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8360 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8361 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8364 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8367 for (i = 0;i < numelements;i++)
8368 outelement3i[i] = inelement3i[i] + adjust;
8371 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8372 extern cvar_t gl_vbo;
8373 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8381 int surfacefirsttriangle;
8382 int surfacenumtriangles;
8383 int surfacefirstvertex;
8384 int surfaceendvertex;
8385 int surfacenumvertices;
8386 int batchnumvertices;
8387 int batchnumtriangles;
8391 qboolean dynamicvertex;
8395 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8397 q3shaderinfo_deform_t *deform;
8398 const msurface_t *surface, *firstsurface;
8399 r_vertexmesh_t *vertexmesh;
8400 if (!texturenumsurfaces)
8402 // find vertex range of this surface batch
8404 firstsurface = texturesurfacelist[0];
8405 firsttriangle = firstsurface->num_firsttriangle;
8406 batchnumvertices = 0;
8407 batchnumtriangles = 0;
8408 firstvertex = endvertex = firstsurface->num_firstvertex;
8409 for (i = 0;i < texturenumsurfaces;i++)
8411 surface = texturesurfacelist[i];
8412 if (surface != firstsurface + i)
8414 surfacefirstvertex = surface->num_firstvertex;
8415 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8416 surfacenumvertices = surface->num_vertices;
8417 surfacenumtriangles = surface->num_triangles;
8418 if (firstvertex > surfacefirstvertex)
8419 firstvertex = surfacefirstvertex;
8420 if (endvertex < surfaceendvertex)
8421 endvertex = surfaceendvertex;
8422 batchnumvertices += surfacenumvertices;
8423 batchnumtriangles += surfacenumtriangles;
8426 // we now know the vertex range used, and if there are any gaps in it
8427 rsurface.batchfirstvertex = firstvertex;
8428 rsurface.batchnumvertices = endvertex - firstvertex;
8429 rsurface.batchfirsttriangle = firsttriangle;
8430 rsurface.batchnumtriangles = batchnumtriangles;
8432 // this variable holds flags for which properties have been updated that
8433 // may require regenerating vertexmesh array...
8436 // check if any dynamic vertex processing must occur
8437 dynamicvertex = false;
8439 // if there is a chance of animated vertex colors, it's a dynamic batch
8440 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8442 dynamicvertex = true;
8443 batchneed |= BATCHNEED_NOGAPS;
8444 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8447 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8449 switch (deform->deform)
8452 case Q3DEFORM_PROJECTIONSHADOW:
8453 case Q3DEFORM_TEXT0:
8454 case Q3DEFORM_TEXT1:
8455 case Q3DEFORM_TEXT2:
8456 case Q3DEFORM_TEXT3:
8457 case Q3DEFORM_TEXT4:
8458 case Q3DEFORM_TEXT5:
8459 case Q3DEFORM_TEXT6:
8460 case Q3DEFORM_TEXT7:
8463 case Q3DEFORM_AUTOSPRITE:
8464 dynamicvertex = true;
8465 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8466 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8468 case Q3DEFORM_AUTOSPRITE2:
8469 dynamicvertex = true;
8470 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8471 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8473 case Q3DEFORM_NORMAL:
8474 dynamicvertex = true;
8475 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8476 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8479 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8480 break; // if wavefunc is a nop, ignore this transform
8481 dynamicvertex = true;
8482 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8483 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8485 case Q3DEFORM_BULGE:
8486 dynamicvertex = true;
8487 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8488 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8491 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8492 break; // if wavefunc is a nop, ignore this transform
8493 dynamicvertex = true;
8494 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8495 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8499 switch(rsurface.texture->tcgen.tcgen)
8502 case Q3TCGEN_TEXTURE:
8504 case Q3TCGEN_LIGHTMAP:
8505 dynamicvertex = true;
8506 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8507 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8509 case Q3TCGEN_VECTOR:
8510 dynamicvertex = true;
8511 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8512 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8514 case Q3TCGEN_ENVIRONMENT:
8515 dynamicvertex = true;
8516 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8517 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8520 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8522 dynamicvertex = true;
8523 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8524 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8527 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8529 dynamicvertex = true;
8530 batchneed |= BATCHNEED_NOGAPS;
8531 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8534 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8536 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8537 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
8538 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
8539 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
8540 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8541 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8542 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8545 // when the model data has no vertex buffer (dynamic mesh), we need to
8547 if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8548 batchneed |= BATCHNEED_NOGAPS;
8550 // if needsupdate, we have to do a dynamic vertex batch for sure
8551 if (needsupdate & batchneed)
8552 dynamicvertex = true;
8554 // see if we need to build vertexmesh from arrays
8555 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8556 dynamicvertex = true;
8558 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8559 // also some drivers strongly dislike firstvertex
8560 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8561 dynamicvertex = true;
8563 rsurface.batchvertex3f = rsurface.modelvertex3f;
8564 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8565 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8566 rsurface.batchsvector3f = rsurface.modelsvector3f;
8567 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8568 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8569 rsurface.batchtvector3f = rsurface.modeltvector3f;
8570 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8571 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8572 rsurface.batchnormal3f = rsurface.modelnormal3f;
8573 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8574 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8575 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8576 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
8577 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8578 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8579 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
8580 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
8581 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8582 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8583 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8584 rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8585 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8586 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8587 rsurface.batchelement3i = rsurface.modelelement3i;
8588 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8589 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8590 rsurface.batchelement3s = rsurface.modelelement3s;
8591 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8592 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8594 // if any dynamic vertex processing has to occur in software, we copy the
8595 // entire surface list together before processing to rebase the vertices
8596 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8598 // if any gaps exist and we do not have a static vertex buffer, we have to
8599 // copy the surface list together to avoid wasting upload bandwidth on the
8600 // vertices in the gaps.
8602 // if gaps exist and we have a static vertex buffer, we still have to
8603 // combine the index buffer ranges into one dynamic index buffer.
8605 // in all cases we end up with data that can be drawn in one call.
8609 // static vertex data, just set pointers...
8610 rsurface.batchgeneratedvertex = false;
8611 // if there are gaps, we want to build a combined index buffer,
8612 // otherwise use the original static buffer with an appropriate offset
8615 // build a new triangle elements array for this batch
8616 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8617 rsurface.batchfirsttriangle = 0;
8619 for (i = 0;i < texturenumsurfaces;i++)
8621 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8622 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8623 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8624 numtriangles += surfacenumtriangles;
8626 rsurface.batchelement3i_indexbuffer = NULL;
8627 rsurface.batchelement3i_bufferoffset = 0;
8628 rsurface.batchelement3s = NULL;
8629 rsurface.batchelement3s_indexbuffer = NULL;
8630 rsurface.batchelement3s_bufferoffset = 0;
8631 if (endvertex <= 65536)
8633 // make a 16bit (unsigned short) index array if possible
8634 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8635 for (i = 0;i < numtriangles*3;i++)
8636 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8642 // something needs software processing, do it for real...
8643 // we only directly handle separate array data in this case and then
8644 // generate interleaved data if needed...
8645 rsurface.batchgeneratedvertex = true;
8647 // now copy the vertex data into a combined array and make an index array
8648 // (this is what Quake3 does all the time)
8649 //if (gaps || rsurface.batchfirstvertex)
8651 rsurface.batchvertex3fbuffer = NULL;
8652 rsurface.batchvertexmesh = NULL;
8653 rsurface.batchvertexmeshbuffer = NULL;
8654 rsurface.batchvertex3f = NULL;
8655 rsurface.batchvertex3f_vertexbuffer = NULL;
8656 rsurface.batchvertex3f_bufferoffset = 0;
8657 rsurface.batchsvector3f = NULL;
8658 rsurface.batchsvector3f_vertexbuffer = NULL;
8659 rsurface.batchsvector3f_bufferoffset = 0;
8660 rsurface.batchtvector3f = NULL;
8661 rsurface.batchtvector3f_vertexbuffer = NULL;
8662 rsurface.batchtvector3f_bufferoffset = 0;
8663 rsurface.batchnormal3f = NULL;
8664 rsurface.batchnormal3f_vertexbuffer = NULL;
8665 rsurface.batchnormal3f_bufferoffset = 0;
8666 rsurface.batchlightmapcolor4f = NULL;
8667 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8668 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8669 rsurface.batchtexcoordtexture2f = NULL;
8670 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8671 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8672 rsurface.batchtexcoordlightmap2f = NULL;
8673 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8674 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8675 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8676 rsurface.batchelement3i_indexbuffer = NULL;
8677 rsurface.batchelement3i_bufferoffset = 0;
8678 rsurface.batchelement3s = NULL;
8679 rsurface.batchelement3s_indexbuffer = NULL;
8680 rsurface.batchelement3s_bufferoffset = 0;
8681 // we'll only be setting up certain arrays as needed
8682 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8683 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8684 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8685 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8686 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8687 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8688 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8690 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8691 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8693 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8694 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8695 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8696 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8697 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8698 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8701 for (i = 0;i < texturenumsurfaces;i++)
8703 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8704 surfacenumvertices = texturesurfacelist[i]->num_vertices;
8705 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8706 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8707 // copy only the data requested
8708 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8709 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8710 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8712 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8714 if (rsurface.batchvertex3f)
8715 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8717 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8719 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8721 if (rsurface.modelnormal3f)
8722 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8724 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8726 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8728 if (rsurface.modelsvector3f)
8730 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8731 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8735 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8736 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8739 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8741 if (rsurface.modellightmapcolor4f)
8742 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8744 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
8746 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8748 if (rsurface.modeltexcoordtexture2f)
8749 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8751 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8753 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8755 if (rsurface.modeltexcoordlightmap2f)
8756 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8758 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8761 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8762 numvertices += surfacenumvertices;
8763 numtriangles += surfacenumtriangles;
8766 // generate a 16bit index array as well if possible
8767 // (in general, dynamic batches fit)
8768 if (numvertices <= 65536)
8770 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8771 for (i = 0;i < numtriangles*3;i++)
8772 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8775 // since we've copied everything, the batch now starts at 0
8776 rsurface.batchfirstvertex = 0;
8777 rsurface.batchnumvertices = batchnumvertices;
8778 rsurface.batchfirsttriangle = 0;
8779 rsurface.batchnumtriangles = batchnumtriangles;
8782 // q1bsp surfaces rendered in vertex color mode have to have colors
8783 // calculated based on lightstyles
8784 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8786 // generate color arrays for the surfaces in this list
8791 const unsigned char *lm;
8792 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8793 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8794 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8796 for (i = 0;i < texturenumsurfaces;i++)
8798 surface = texturesurfacelist[i];
8799 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8800 surfacenumvertices = surface->num_vertices;
8801 if (surface->lightmapinfo->samples)
8803 for (j = 0;j < surfacenumvertices;j++)
8805 lm = surface->lightmapinfo->samples + offsets[j];
8806 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8807 VectorScale(lm, scale, c);
8808 if (surface->lightmapinfo->styles[1] != 255)
8810 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8812 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8813 VectorMA(c, scale, lm, c);
8814 if (surface->lightmapinfo->styles[2] != 255)
8817 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8818 VectorMA(c, scale, lm, c);
8819 if (surface->lightmapinfo->styles[3] != 255)
8822 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8823 VectorMA(c, scale, lm, c);
8830 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);
8836 for (j = 0;j < surfacenumvertices;j++)
8838 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8845 // if vertices are deformed (sprite flares and things in maps, possibly
8846 // water waves, bulges and other deformations), modify the copied vertices
8848 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8850 switch (deform->deform)
8853 case Q3DEFORM_PROJECTIONSHADOW:
8854 case Q3DEFORM_TEXT0:
8855 case Q3DEFORM_TEXT1:
8856 case Q3DEFORM_TEXT2:
8857 case Q3DEFORM_TEXT3:
8858 case Q3DEFORM_TEXT4:
8859 case Q3DEFORM_TEXT5:
8860 case Q3DEFORM_TEXT6:
8861 case Q3DEFORM_TEXT7:
8864 case Q3DEFORM_AUTOSPRITE:
8865 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8866 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8867 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8868 VectorNormalize(newforward);
8869 VectorNormalize(newright);
8870 VectorNormalize(newup);
8871 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8872 // rsurface.batchvertex3f_vertexbuffer = NULL;
8873 // rsurface.batchvertex3f_bufferoffset = 0;
8874 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8875 // rsurface.batchsvector3f_vertexbuffer = NULL;
8876 // rsurface.batchsvector3f_bufferoffset = 0;
8877 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8878 // rsurface.batchtvector3f_vertexbuffer = NULL;
8879 // rsurface.batchtvector3f_bufferoffset = 0;
8880 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8881 // rsurface.batchnormal3f_vertexbuffer = NULL;
8882 // rsurface.batchnormal3f_bufferoffset = 0;
8883 // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
8884 if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
8885 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8886 if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
8887 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);
8888 // a single autosprite surface can contain multiple sprites...
8889 for (j = 0;j < batchnumvertices - 3;j += 4)
8891 VectorClear(center);
8892 for (i = 0;i < 4;i++)
8893 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8894 VectorScale(center, 0.25f, center);
8895 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8896 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8897 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8898 for (i = 0;i < 4;i++)
8900 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8901 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8904 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8905 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8906 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);
8908 case Q3DEFORM_AUTOSPRITE2:
8909 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8910 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8911 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8912 VectorNormalize(newforward);
8913 VectorNormalize(newright);
8914 VectorNormalize(newup);
8915 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8916 // rsurface.batchvertex3f_vertexbuffer = NULL;
8917 // rsurface.batchvertex3f_bufferoffset = 0;
8919 const float *v1, *v2;
8929 memset(shortest, 0, sizeof(shortest));
8930 // a single autosprite surface can contain multiple sprites...
8931 for (j = 0;j < batchnumvertices - 3;j += 4)
8933 VectorClear(center);
8934 for (i = 0;i < 4;i++)
8935 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8936 VectorScale(center, 0.25f, center);
8937 // find the two shortest edges, then use them to define the
8938 // axis vectors for rotating around the central axis
8939 for (i = 0;i < 6;i++)
8941 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8942 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8943 l = VectorDistance2(v1, v2);
8944 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8946 l += (1.0f / 1024.0f);
8947 if (shortest[0].length2 > l || i == 0)
8949 shortest[1] = shortest[0];
8950 shortest[0].length2 = l;
8951 shortest[0].v1 = v1;
8952 shortest[0].v2 = v2;
8954 else if (shortest[1].length2 > l || i == 1)
8956 shortest[1].length2 = l;
8957 shortest[1].v1 = v1;
8958 shortest[1].v2 = v2;
8961 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8962 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8963 // this calculates the right vector from the shortest edge
8964 // and the up vector from the edge midpoints
8965 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8966 VectorNormalize(right);
8967 VectorSubtract(end, start, up);
8968 VectorNormalize(up);
8969 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8970 VectorSubtract(rsurface.localvieworigin, center, forward);
8971 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8972 VectorNegate(forward, forward);
8973 VectorReflect(forward, 0, up, forward);
8974 VectorNormalize(forward);
8975 CrossProduct(up, forward, newright);
8976 VectorNormalize(newright);
8977 // rotate the quad around the up axis vector, this is made
8978 // especially easy by the fact we know the quad is flat,
8979 // so we only have to subtract the center position and
8980 // measure distance along the right vector, and then
8981 // multiply that by the newright vector and add back the
8983 // we also need to subtract the old position to undo the
8984 // displacement from the center, which we do with a
8985 // DotProduct, the subtraction/addition of center is also
8986 // optimized into DotProducts here
8987 l = DotProduct(right, center);
8988 for (i = 0;i < 4;i++)
8990 v1 = rsurface.batchvertex3f + 3*(j+i);
8991 f = DotProduct(right, v1) - l;
8992 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8996 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8998 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8999 // rsurface.batchnormal3f_vertexbuffer = NULL;
9000 // rsurface.batchnormal3f_bufferoffset = 0;
9001 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9003 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9005 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9006 // rsurface.batchsvector3f_vertexbuffer = NULL;
9007 // rsurface.batchsvector3f_bufferoffset = 0;
9008 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9009 // rsurface.batchtvector3f_vertexbuffer = NULL;
9010 // rsurface.batchtvector3f_bufferoffset = 0;
9011 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);
9014 case Q3DEFORM_NORMAL:
9015 // deform the normals to make reflections wavey
9016 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9017 rsurface.batchnormal3f_vertexbuffer = NULL;
9018 rsurface.batchnormal3f_bufferoffset = 0;
9019 for (j = 0;j < batchnumvertices;j++)
9022 float *normal = rsurface.batchnormal3f + 3*j;
9023 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9024 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9025 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9026 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9027 VectorNormalize(normal);
9029 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9031 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9032 // rsurface.batchsvector3f_vertexbuffer = NULL;
9033 // rsurface.batchsvector3f_bufferoffset = 0;
9034 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9035 // rsurface.batchtvector3f_vertexbuffer = NULL;
9036 // rsurface.batchtvector3f_bufferoffset = 0;
9037 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);
9041 // deform vertex array to make wavey water and flags and such
9042 waveparms[0] = deform->waveparms[0];
9043 waveparms[1] = deform->waveparms[1];
9044 waveparms[2] = deform->waveparms[2];
9045 waveparms[3] = deform->waveparms[3];
9046 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9047 break; // if wavefunc is a nop, don't make a dynamic vertex array
9048 // this is how a divisor of vertex influence on deformation
9049 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9050 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9051 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9052 // rsurface.batchvertex3f_vertexbuffer = NULL;
9053 // rsurface.batchvertex3f_bufferoffset = 0;
9054 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9055 // rsurface.batchnormal3f_vertexbuffer = NULL;
9056 // rsurface.batchnormal3f_bufferoffset = 0;
9057 for (j = 0;j < batchnumvertices;j++)
9059 // if the wavefunc depends on time, evaluate it per-vertex
9062 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9063 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9065 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9067 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9068 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9069 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9071 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9072 // rsurface.batchsvector3f_vertexbuffer = NULL;
9073 // rsurface.batchsvector3f_bufferoffset = 0;
9074 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9075 // rsurface.batchtvector3f_vertexbuffer = NULL;
9076 // rsurface.batchtvector3f_bufferoffset = 0;
9077 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);
9080 case Q3DEFORM_BULGE:
9081 // deform vertex array to make the surface have moving bulges
9082 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9083 // rsurface.batchvertex3f_vertexbuffer = NULL;
9084 // rsurface.batchvertex3f_bufferoffset = 0;
9085 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9086 // rsurface.batchnormal3f_vertexbuffer = NULL;
9087 // rsurface.batchnormal3f_bufferoffset = 0;
9088 for (j = 0;j < batchnumvertices;j++)
9090 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9091 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9093 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9094 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9095 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9097 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9098 // rsurface.batchsvector3f_vertexbuffer = NULL;
9099 // rsurface.batchsvector3f_bufferoffset = 0;
9100 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9101 // rsurface.batchtvector3f_vertexbuffer = NULL;
9102 // rsurface.batchtvector3f_bufferoffset = 0;
9103 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);
9107 // deform vertex array
9108 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9109 break; // if wavefunc is a nop, don't make a dynamic vertex array
9110 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9111 VectorScale(deform->parms, scale, waveparms);
9112 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9113 // rsurface.batchvertex3f_vertexbuffer = NULL;
9114 // rsurface.batchvertex3f_bufferoffset = 0;
9115 for (j = 0;j < batchnumvertices;j++)
9116 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9121 // generate texcoords based on the chosen texcoord source
9122 switch(rsurface.texture->tcgen.tcgen)
9125 case Q3TCGEN_TEXTURE:
9127 case Q3TCGEN_LIGHTMAP:
9128 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9129 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9130 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9131 if (rsurface.batchtexcoordlightmap2f)
9132 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9134 case Q3TCGEN_VECTOR:
9135 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9136 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9137 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9138 for (j = 0;j < batchnumvertices;j++)
9140 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9141 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9144 case Q3TCGEN_ENVIRONMENT:
9145 // make environment reflections using a spheremap
9146 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9147 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9148 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9149 for (j = 0;j < batchnumvertices;j++)
9151 // identical to Q3A's method, but executed in worldspace so
9152 // carried models can be shiny too
9154 float viewer[3], d, reflected[3], worldreflected[3];
9156 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9157 // VectorNormalize(viewer);
9159 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9161 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9162 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9163 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9164 // note: this is proportinal to viewer, so we can normalize later
9166 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9167 VectorNormalize(worldreflected);
9169 // note: this sphere map only uses world x and z!
9170 // so positive and negative y will LOOK THE SAME.
9171 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9172 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9176 // the only tcmod that needs software vertex processing is turbulent, so
9177 // check for it here and apply the changes if needed
9178 // and we only support that as the first one
9179 // (handling a mixture of turbulent and other tcmods would be problematic
9180 // without punting it entirely to a software path)
9181 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9183 amplitude = rsurface.texture->tcmods[0].parms[1];
9184 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9185 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9186 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9187 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9188 for (j = 0;j < batchnumvertices;j++)
9190 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);
9191 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9195 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9197 // convert the modified arrays to vertex structs
9198 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9199 // rsurface.batchvertexmeshbuffer = NULL;
9200 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9201 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9202 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9203 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9204 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9205 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9206 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9208 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9210 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9211 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9214 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9215 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9216 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9217 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9218 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9219 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9220 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9221 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9222 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9226 void RSurf_DrawBatch(void)
9228 // sometimes a zero triangle surface (usually a degenerate patch) makes it
9229 // through the pipeline, killing it earlier in the pipeline would have
9230 // per-surface overhead rather than per-batch overhead, so it's best to
9231 // reject it here, before it hits glDraw.
9232 if (rsurface.batchnumtriangles == 0)
9235 // batch debugging code
9236 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9242 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9243 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9246 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9248 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9250 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9251 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);
9258 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);
9261 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9263 // pick the closest matching water plane
9264 int planeindex, vertexindex, bestplaneindex = -1;
9268 r_waterstate_waterplane_t *p;
9269 qboolean prepared = false;
9271 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9273 if(p->camera_entity != rsurface.texture->camera_entity)
9278 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9280 if(rsurface.batchnumvertices == 0)
9283 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9285 Matrix4x4_Transform(&rsurface.matrix, v, vert);
9286 d += fabs(PlaneDiff(vert, &p->plane));
9288 if (bestd > d || bestplaneindex < 0)
9291 bestplaneindex = planeindex;
9294 return bestplaneindex;
9295 // NOTE: this MAY return a totally unrelated water plane; we can ignore
9296 // this situation though, as it might be better to render single larger
9297 // batches with useless stuff (backface culled for example) than to
9298 // render multiple smaller batches
9301 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9304 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9305 rsurface.passcolor4f_vertexbuffer = 0;
9306 rsurface.passcolor4f_bufferoffset = 0;
9307 for (i = 0;i < rsurface.batchnumvertices;i++)
9308 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9311 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9318 if (rsurface.passcolor4f)
9320 // generate color arrays
9321 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9322 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9323 rsurface.passcolor4f_vertexbuffer = 0;
9324 rsurface.passcolor4f_bufferoffset = 0;
9325 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)
9327 f = RSurf_FogVertex(v);
9336 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9337 rsurface.passcolor4f_vertexbuffer = 0;
9338 rsurface.passcolor4f_bufferoffset = 0;
9339 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9341 f = RSurf_FogVertex(v);
9350 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9357 if (!rsurface.passcolor4f)
9359 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9360 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9361 rsurface.passcolor4f_vertexbuffer = 0;
9362 rsurface.passcolor4f_bufferoffset = 0;
9363 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)
9365 f = RSurf_FogVertex(v);
9366 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9367 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9368 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9373 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9378 if (!rsurface.passcolor4f)
9380 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9381 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9382 rsurface.passcolor4f_vertexbuffer = 0;
9383 rsurface.passcolor4f_bufferoffset = 0;
9384 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9393 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9398 if (!rsurface.passcolor4f)
9400 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9401 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9402 rsurface.passcolor4f_vertexbuffer = 0;
9403 rsurface.passcolor4f_bufferoffset = 0;
9404 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9406 c2[0] = c[0] + r_refdef.scene.ambient;
9407 c2[1] = c[1] + r_refdef.scene.ambient;
9408 c2[2] = c[2] + r_refdef.scene.ambient;
9413 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9416 rsurface.passcolor4f = NULL;
9417 rsurface.passcolor4f_vertexbuffer = 0;
9418 rsurface.passcolor4f_bufferoffset = 0;
9419 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9420 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9421 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9422 GL_Color(r, g, b, a);
9423 R_Mesh_TexBind(0, rsurface.lightmaptexture);
9427 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9429 // TODO: optimize applyfog && applycolor case
9430 // just apply fog if necessary, and tint the fog color array if necessary
9431 rsurface.passcolor4f = NULL;
9432 rsurface.passcolor4f_vertexbuffer = 0;
9433 rsurface.passcolor4f_bufferoffset = 0;
9434 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9435 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9436 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9437 GL_Color(r, g, b, a);
9441 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9444 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9445 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9446 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9447 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9448 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9449 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9450 GL_Color(r, g, b, a);
9454 static void RSurf_DrawBatch_GL11_ClampColor(void)
9459 if (!rsurface.passcolor4f)
9461 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9463 c2[0] = bound(0.0f, c1[0], 1.0f);
9464 c2[1] = bound(0.0f, c1[1], 1.0f);
9465 c2[2] = bound(0.0f, c1[2], 1.0f);
9466 c2[3] = bound(0.0f, c1[3], 1.0f);
9470 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9480 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9481 rsurface.passcolor4f_vertexbuffer = 0;
9482 rsurface.passcolor4f_bufferoffset = 0;
9483 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)
9485 f = -DotProduct(r_refdef.view.forward, n);
9487 f = f * 0.85 + 0.15; // work around so stuff won't get black
9488 f *= r_refdef.lightmapintensity;
9489 Vector4Set(c, f, f, f, 1);
9493 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9495 RSurf_DrawBatch_GL11_ApplyFakeLight();
9496 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9497 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9498 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9499 GL_Color(r, g, b, a);
9503 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9511 vec3_t ambientcolor;
9512 vec3_t diffusecolor;
9516 VectorCopy(rsurface.modellight_lightdir, lightdir);
9517 f = 0.5f * r_refdef.lightmapintensity;
9518 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9519 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9520 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9521 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9522 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9523 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9525 if (VectorLength2(diffusecolor) > 0)
9527 // q3-style directional shading
9528 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9529 rsurface.passcolor4f_vertexbuffer = 0;
9530 rsurface.passcolor4f_bufferoffset = 0;
9531 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)
9533 if ((f = DotProduct(n, lightdir)) > 0)
9534 VectorMA(ambientcolor, f, diffusecolor, c);
9536 VectorCopy(ambientcolor, c);
9543 *applycolor = false;
9547 *r = ambientcolor[0];
9548 *g = ambientcolor[1];
9549 *b = ambientcolor[2];
9550 rsurface.passcolor4f = NULL;
9551 rsurface.passcolor4f_vertexbuffer = 0;
9552 rsurface.passcolor4f_bufferoffset = 0;
9556 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9558 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9559 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9560 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9561 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9562 GL_Color(r, g, b, a);
9566 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9574 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9575 rsurface.passcolor4f_vertexbuffer = 0;
9576 rsurface.passcolor4f_bufferoffset = 0;
9578 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9580 f = 1 - RSurf_FogVertex(v);
9588 void RSurf_SetupDepthAndCulling(void)
9590 // submodels are biased to avoid z-fighting with world surfaces that they
9591 // may be exactly overlapping (avoids z-fighting artifacts on certain
9592 // doors and things in Quake maps)
9593 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9594 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9595 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9596 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9599 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9601 // transparent sky would be ridiculous
9602 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9604 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
9605 skyrenderlater = true;
9606 RSurf_SetupDepthAndCulling();
9608 // LordHavoc: HalfLife maps have freaky skypolys so don't use
9609 // skymasking on them, and Quake3 never did sky masking (unlike
9610 // software Quake and software Quake2), so disable the sky masking
9611 // in Quake3 maps as it causes problems with q3map2 sky tricks,
9612 // and skymasking also looks very bad when noclipping outside the
9613 // level, so don't use it then either.
9614 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
9616 R_Mesh_ResetTextureState();
9617 if (skyrendermasked)
9619 R_SetupShader_DepthOrShadow(false);
9620 // depth-only (masking)
9621 GL_ColorMask(0,0,0,0);
9622 // just to make sure that braindead drivers don't draw
9623 // anything despite that colormask...
9624 GL_BlendFunc(GL_ZERO, GL_ONE);
9625 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9626 if (rsurface.batchvertex3fbuffer)
9627 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9629 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9633 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
9635 GL_BlendFunc(GL_ONE, GL_ZERO);
9636 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9637 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9638 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9641 if (skyrendermasked)
9642 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9644 R_Mesh_ResetTextureState();
9645 GL_Color(1, 1, 1, 1);
9648 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9649 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9650 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9652 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9656 // render screenspace normalmap to texture
9658 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
9662 // bind lightmap texture
9664 // water/refraction/reflection/camera surfaces have to be handled specially
9665 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9667 int start, end, startplaneindex;
9668 for (start = 0;start < texturenumsurfaces;start = end)
9670 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9671 if(startplaneindex < 0)
9673 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9674 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9678 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9680 // now that we have a batch using the same planeindex, render it
9681 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9683 // render water or distortion background
9685 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);
9687 // blend surface on top
9688 GL_DepthMask(false);
9689 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
9692 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9694 // render surface with reflection texture as input
9695 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9696 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);
9703 // render surface batch normally
9704 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9705 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);
9709 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9711 // OpenGL 1.3 path - anything not completely ancient
9712 qboolean applycolor;
9715 const texturelayer_t *layer;
9716 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);
9717 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9719 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9722 int layertexrgbscale;
9723 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9725 if (layerindex == 0)
9729 GL_AlphaTest(false);
9730 GL_DepthFunc(GL_EQUAL);
9733 GL_DepthMask(layer->depthmask && writedepth);
9734 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9735 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9737 layertexrgbscale = 4;
9738 VectorScale(layer->color, 0.25f, layercolor);
9740 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9742 layertexrgbscale = 2;
9743 VectorScale(layer->color, 0.5f, layercolor);
9747 layertexrgbscale = 1;
9748 VectorScale(layer->color, 1.0f, layercolor);
9750 layercolor[3] = layer->color[3];
9751 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9752 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9753 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9754 switch (layer->type)
9756 case TEXTURELAYERTYPE_LITTEXTURE:
9757 // single-pass lightmapped texture with 2x rgbscale
9758 R_Mesh_TexBind(0, r_texture_white);
9759 R_Mesh_TexMatrix(0, NULL);
9760 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9761 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9762 R_Mesh_TexBind(1, layer->texture);
9763 R_Mesh_TexMatrix(1, &layer->texmatrix);
9764 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9765 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9766 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9767 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9768 else if (FAKELIGHT_ENABLED)
9769 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9770 else if (rsurface.uselightmaptexture)
9771 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9773 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9775 case TEXTURELAYERTYPE_TEXTURE:
9776 // singletexture unlit texture with transparency support
9777 R_Mesh_TexBind(0, layer->texture);
9778 R_Mesh_TexMatrix(0, &layer->texmatrix);
9779 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9780 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9781 R_Mesh_TexBind(1, 0);
9782 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9783 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9785 case TEXTURELAYERTYPE_FOG:
9786 // singletexture fogging
9789 R_Mesh_TexBind(0, layer->texture);
9790 R_Mesh_TexMatrix(0, &layer->texmatrix);
9791 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9792 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9796 R_Mesh_TexBind(0, 0);
9797 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9799 R_Mesh_TexBind(1, 0);
9800 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9801 // generate a color array for the fog pass
9802 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9803 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9807 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9810 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9812 GL_DepthFunc(GL_LEQUAL);
9813 GL_AlphaTest(false);
9817 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9819 // OpenGL 1.1 - crusty old voodoo path
9822 const texturelayer_t *layer;
9823 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);
9824 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9826 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9828 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9830 if (layerindex == 0)
9834 GL_AlphaTest(false);
9835 GL_DepthFunc(GL_EQUAL);
9838 GL_DepthMask(layer->depthmask && writedepth);
9839 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9840 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9841 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9842 switch (layer->type)
9844 case TEXTURELAYERTYPE_LITTEXTURE:
9845 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9847 // two-pass lit texture with 2x rgbscale
9848 // first the lightmap pass
9849 R_Mesh_TexBind(0, r_texture_white);
9850 R_Mesh_TexMatrix(0, NULL);
9851 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9852 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9853 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9854 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9855 else if (FAKELIGHT_ENABLED)
9856 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9857 else if (rsurface.uselightmaptexture)
9858 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9860 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9861 // then apply the texture to it
9862 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9863 R_Mesh_TexBind(0, layer->texture);
9864 R_Mesh_TexMatrix(0, &layer->texmatrix);
9865 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9866 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9867 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);
9871 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9872 R_Mesh_TexBind(0, layer->texture);
9873 R_Mesh_TexMatrix(0, &layer->texmatrix);
9874 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9875 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9876 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9877 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);
9879 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);
9882 case TEXTURELAYERTYPE_TEXTURE:
9883 // singletexture unlit texture with transparency support
9884 R_Mesh_TexBind(0, layer->texture);
9885 R_Mesh_TexMatrix(0, &layer->texmatrix);
9886 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9887 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9888 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);
9890 case TEXTURELAYERTYPE_FOG:
9891 // singletexture fogging
9894 R_Mesh_TexBind(0, layer->texture);
9895 R_Mesh_TexMatrix(0, &layer->texmatrix);
9896 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9897 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9901 R_Mesh_TexBind(0, 0);
9902 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9904 // generate a color array for the fog pass
9905 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9906 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9910 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9913 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9915 GL_DepthFunc(GL_LEQUAL);
9916 GL_AlphaTest(false);
9920 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9924 r_vertexgeneric_t *batchvertex;
9927 // R_Mesh_ResetTextureState();
9928 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
9930 if(rsurface.texture && rsurface.texture->currentskinframe)
9932 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9933 c[3] *= rsurface.texture->currentalpha;
9943 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9945 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9946 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9947 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9950 // brighten it up (as texture value 127 means "unlit")
9951 c[0] *= 2 * r_refdef.view.colorscale;
9952 c[1] *= 2 * r_refdef.view.colorscale;
9953 c[2] *= 2 * r_refdef.view.colorscale;
9955 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9956 c[3] *= r_wateralpha.value;
9958 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9960 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9961 GL_DepthMask(false);
9963 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9965 GL_BlendFunc(GL_ONE, GL_ONE);
9966 GL_DepthMask(false);
9968 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9970 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9971 GL_DepthMask(false);
9973 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9975 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9976 GL_DepthMask(false);
9980 GL_BlendFunc(GL_ONE, GL_ZERO);
9981 GL_DepthMask(writedepth);
9984 if (r_showsurfaces.integer == 3)
9986 rsurface.passcolor4f = NULL;
9988 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9990 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9992 rsurface.passcolor4f = NULL;
9993 rsurface.passcolor4f_vertexbuffer = 0;
9994 rsurface.passcolor4f_bufferoffset = 0;
9996 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9998 qboolean applycolor = true;
10001 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10003 r_refdef.lightmapintensity = 1;
10004 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10005 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10007 else if (FAKELIGHT_ENABLED)
10009 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10011 r_refdef.lightmapintensity = r_fakelight_intensity.value;
10012 RSurf_DrawBatch_GL11_ApplyFakeLight();
10013 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10017 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10019 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10020 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10021 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10024 if(!rsurface.passcolor4f)
10025 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10027 RSurf_DrawBatch_GL11_ApplyAmbient();
10028 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10029 if(r_refdef.fogenabled)
10030 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10031 RSurf_DrawBatch_GL11_ClampColor();
10033 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10034 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
10037 else if (!r_refdef.view.showdebug)
10039 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10040 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10041 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10043 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10044 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10046 R_Mesh_PrepareVertices_Generic_Unlock();
10049 else if (r_showsurfaces.integer == 4)
10051 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10052 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10053 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10055 unsigned char c = (vi << 3) * (1.0f / 256.0f);
10056 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10057 Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10059 R_Mesh_PrepareVertices_Generic_Unlock();
10062 else if (r_showsurfaces.integer == 2)
10065 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10066 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10067 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10069 unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10070 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10071 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10072 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10073 Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10074 Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10075 Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10077 R_Mesh_PrepareVertices_Generic_Unlock();
10078 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10082 int texturesurfaceindex;
10084 const msurface_t *surface;
10085 float surfacecolor4f[4];
10086 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10087 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10089 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10091 surface = texturesurfacelist[texturesurfaceindex];
10092 k = (int)(((size_t)surface) / sizeof(msurface_t));
10093 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10094 for (j = 0;j < surface->num_vertices;j++)
10096 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10097 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10101 R_Mesh_PrepareVertices_Generic_Unlock();
10106 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10109 RSurf_SetupDepthAndCulling();
10110 if (r_showsurfaces.integer)
10112 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10115 switch (vid.renderpath)
10117 case RENDERPATH_GL20:
10118 case RENDERPATH_D3D9:
10119 case RENDERPATH_D3D10:
10120 case RENDERPATH_D3D11:
10121 case RENDERPATH_SOFT:
10122 case RENDERPATH_GLES2:
10123 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10125 case RENDERPATH_GL13:
10126 case RENDERPATH_GLES1:
10127 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10129 case RENDERPATH_GL11:
10130 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10136 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10139 RSurf_SetupDepthAndCulling();
10140 if (r_showsurfaces.integer)
10142 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10145 switch (vid.renderpath)
10147 case RENDERPATH_GL20:
10148 case RENDERPATH_D3D9:
10149 case RENDERPATH_D3D10:
10150 case RENDERPATH_D3D11:
10151 case RENDERPATH_SOFT:
10152 case RENDERPATH_GLES2:
10153 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10155 case RENDERPATH_GL13:
10156 case RENDERPATH_GLES1:
10157 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10159 case RENDERPATH_GL11:
10160 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10166 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10169 int texturenumsurfaces, endsurface;
10170 texture_t *texture;
10171 const msurface_t *surface;
10172 const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10174 // if the model is static it doesn't matter what value we give for
10175 // wantnormals and wanttangents, so this logic uses only rules applicable
10176 // to a model, knowing that they are meaningless otherwise
10177 if (ent == r_refdef.scene.worldentity)
10178 RSurf_ActiveWorldEntity();
10179 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10180 RSurf_ActiveModelEntity(ent, false, false, false);
10183 switch (vid.renderpath)
10185 case RENDERPATH_GL20:
10186 case RENDERPATH_D3D9:
10187 case RENDERPATH_D3D10:
10188 case RENDERPATH_D3D11:
10189 case RENDERPATH_SOFT:
10190 case RENDERPATH_GLES2:
10191 RSurf_ActiveModelEntity(ent, true, true, false);
10193 case RENDERPATH_GL11:
10194 case RENDERPATH_GL13:
10195 case RENDERPATH_GLES1:
10196 RSurf_ActiveModelEntity(ent, true, false, false);
10201 if (r_transparentdepthmasking.integer)
10203 qboolean setup = false;
10204 for (i = 0;i < numsurfaces;i = j)
10207 surface = rsurface.modelsurfaces + surfacelist[i];
10208 texture = surface->texture;
10209 rsurface.texture = R_GetCurrentTexture(texture);
10210 rsurface.lightmaptexture = NULL;
10211 rsurface.deluxemaptexture = NULL;
10212 rsurface.uselightmaptexture = false;
10213 // scan ahead until we find a different texture
10214 endsurface = min(i + 1024, numsurfaces);
10215 texturenumsurfaces = 0;
10216 texturesurfacelist[texturenumsurfaces++] = surface;
10217 for (;j < endsurface;j++)
10219 surface = rsurface.modelsurfaces + surfacelist[j];
10220 if (texture != surface->texture)
10222 texturesurfacelist[texturenumsurfaces++] = surface;
10224 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10226 // render the range of surfaces as depth
10230 GL_ColorMask(0,0,0,0);
10232 GL_DepthTest(true);
10233 GL_BlendFunc(GL_ONE, GL_ZERO);
10234 GL_DepthMask(true);
10235 // R_Mesh_ResetTextureState();
10236 R_SetupShader_DepthOrShadow(false);
10238 RSurf_SetupDepthAndCulling();
10239 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10240 if (rsurface.batchvertex3fbuffer)
10241 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10243 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10247 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10250 for (i = 0;i < numsurfaces;i = j)
10253 surface = rsurface.modelsurfaces + surfacelist[i];
10254 texture = surface->texture;
10255 rsurface.texture = R_GetCurrentTexture(texture);
10256 // scan ahead until we find a different texture
10257 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10258 texturenumsurfaces = 0;
10259 texturesurfacelist[texturenumsurfaces++] = surface;
10260 if(FAKELIGHT_ENABLED)
10262 rsurface.lightmaptexture = NULL;
10263 rsurface.deluxemaptexture = NULL;
10264 rsurface.uselightmaptexture = false;
10265 for (;j < endsurface;j++)
10267 surface = rsurface.modelsurfaces + surfacelist[j];
10268 if (texture != surface->texture)
10270 texturesurfacelist[texturenumsurfaces++] = surface;
10275 rsurface.lightmaptexture = surface->lightmaptexture;
10276 rsurface.deluxemaptexture = surface->deluxemaptexture;
10277 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10278 for (;j < endsurface;j++)
10280 surface = rsurface.modelsurfaces + surfacelist[j];
10281 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10283 texturesurfacelist[texturenumsurfaces++] = surface;
10286 // render the range of surfaces
10287 if (ent == r_refdef.scene.worldentity)
10288 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10290 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10292 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10295 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10297 // transparent surfaces get pushed off into the transparent queue
10298 int surfacelistindex;
10299 const msurface_t *surface;
10300 vec3_t tempcenter, center;
10301 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10303 surface = texturesurfacelist[surfacelistindex];
10304 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10305 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10306 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10307 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10308 if (queueentity->transparent_offset) // transparent offset
10310 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10311 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10312 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10314 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10318 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10320 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10322 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10324 RSurf_SetupDepthAndCulling();
10325 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10326 if (rsurface.batchvertex3fbuffer)
10327 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10329 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10333 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10335 const entity_render_t *queueentity = r_refdef.scene.worldentity;
10338 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10341 if (!rsurface.texture->currentnumlayers)
10343 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10344 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10346 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10348 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10349 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10350 else if (!rsurface.texture->currentnumlayers)
10352 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10354 // in the deferred case, transparent surfaces were queued during prepass
10355 if (!r_shadow_usingdeferredprepass)
10356 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10360 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10361 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10366 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10369 texture_t *texture;
10370 R_FrameData_SetMark();
10371 // break the surface list down into batches by texture and use of lightmapping
10372 for (i = 0;i < numsurfaces;i = j)
10375 // texture is the base texture pointer, rsurface.texture is the
10376 // current frame/skin the texture is directing us to use (for example
10377 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10378 // use skin 1 instead)
10379 texture = surfacelist[i]->texture;
10380 rsurface.texture = R_GetCurrentTexture(texture);
10381 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10383 // if this texture is not the kind we want, skip ahead to the next one
10384 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10388 if(FAKELIGHT_ENABLED || depthonly || prepass)
10390 rsurface.lightmaptexture = NULL;
10391 rsurface.deluxemaptexture = NULL;
10392 rsurface.uselightmaptexture = false;
10393 // simply scan ahead until we find a different texture or lightmap state
10394 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10399 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10400 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10401 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10402 // simply scan ahead until we find a different texture or lightmap state
10403 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10406 // render the range of surfaces
10407 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10409 R_FrameData_ReturnToMark();
10412 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10416 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10419 if (!rsurface.texture->currentnumlayers)
10421 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10422 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10424 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10426 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10427 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10428 else if (!rsurface.texture->currentnumlayers)
10430 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10432 // in the deferred case, transparent surfaces were queued during prepass
10433 if (!r_shadow_usingdeferredprepass)
10434 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10438 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10439 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10444 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10447 texture_t *texture;
10448 R_FrameData_SetMark();
10449 // break the surface list down into batches by texture and use of lightmapping
10450 for (i = 0;i < numsurfaces;i = j)
10453 // texture is the base texture pointer, rsurface.texture is the
10454 // current frame/skin the texture is directing us to use (for example
10455 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10456 // use skin 1 instead)
10457 texture = surfacelist[i]->texture;
10458 rsurface.texture = R_GetCurrentTexture(texture);
10459 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10461 // if this texture is not the kind we want, skip ahead to the next one
10462 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10466 if(FAKELIGHT_ENABLED || depthonly || prepass)
10468 rsurface.lightmaptexture = NULL;
10469 rsurface.deluxemaptexture = NULL;
10470 rsurface.uselightmaptexture = false;
10471 // simply scan ahead until we find a different texture or lightmap state
10472 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10477 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10478 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10479 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10480 // simply scan ahead until we find a different texture or lightmap state
10481 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10484 // render the range of surfaces
10485 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10487 R_FrameData_ReturnToMark();
10490 float locboxvertex3f[6*4*3] =
10492 1,0,1, 1,0,0, 1,1,0, 1,1,1,
10493 0,1,1, 0,1,0, 0,0,0, 0,0,1,
10494 1,1,1, 1,1,0, 0,1,0, 0,1,1,
10495 0,0,1, 0,0,0, 1,0,0, 1,0,1,
10496 0,0,1, 1,0,1, 1,1,1, 0,1,1,
10497 1,0,0, 0,0,0, 0,1,0, 1,1,0
10500 unsigned short locboxelements[6*2*3] =
10505 12,13,14, 12,14,15,
10506 16,17,18, 16,18,19,
10510 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10513 cl_locnode_t *loc = (cl_locnode_t *)ent;
10515 float vertex3f[6*4*3];
10517 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10518 GL_DepthMask(false);
10519 GL_DepthRange(0, 1);
10520 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10521 GL_DepthTest(true);
10522 GL_CullFace(GL_NONE);
10523 R_EntityMatrix(&identitymatrix);
10525 // R_Mesh_ResetTextureState();
10527 i = surfacelist[0];
10528 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10529 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10530 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10531 surfacelist[0] < 0 ? 0.5f : 0.125f);
10533 if (VectorCompare(loc->mins, loc->maxs))
10535 VectorSet(size, 2, 2, 2);
10536 VectorMA(loc->mins, -0.5f, size, mins);
10540 VectorCopy(loc->mins, mins);
10541 VectorSubtract(loc->maxs, loc->mins, size);
10544 for (i = 0;i < 6*4*3;)
10545 for (j = 0;j < 3;j++, i++)
10546 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10548 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10549 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
10550 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10553 void R_DrawLocs(void)
10556 cl_locnode_t *loc, *nearestloc;
10558 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10559 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10561 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10562 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10566 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10568 if (decalsystem->decals)
10569 Mem_Free(decalsystem->decals);
10570 memset(decalsystem, 0, sizeof(*decalsystem));
10573 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)
10576 tridecal_t *decals;
10579 // expand or initialize the system
10580 if (decalsystem->maxdecals <= decalsystem->numdecals)
10582 decalsystem_t old = *decalsystem;
10583 qboolean useshortelements;
10584 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10585 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10586 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)));
10587 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10588 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10589 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10590 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10591 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10592 if (decalsystem->numdecals)
10593 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10595 Mem_Free(old.decals);
10596 for (i = 0;i < decalsystem->maxdecals*3;i++)
10597 decalsystem->element3i[i] = i;
10598 if (useshortelements)
10599 for (i = 0;i < decalsystem->maxdecals*3;i++)
10600 decalsystem->element3s[i] = i;
10603 // grab a decal and search for another free slot for the next one
10604 decals = decalsystem->decals;
10605 decal = decalsystem->decals + (i = decalsystem->freedecal++);
10606 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10608 decalsystem->freedecal = i;
10609 if (decalsystem->numdecals <= i)
10610 decalsystem->numdecals = i + 1;
10612 // initialize the decal
10614 decal->triangleindex = triangleindex;
10615 decal->surfaceindex = surfaceindex;
10616 decal->decalsequence = decalsequence;
10617 decal->color4f[0][0] = c0[0];
10618 decal->color4f[0][1] = c0[1];
10619 decal->color4f[0][2] = c0[2];
10620 decal->color4f[0][3] = 1;
10621 decal->color4f[1][0] = c1[0];
10622 decal->color4f[1][1] = c1[1];
10623 decal->color4f[1][2] = c1[2];
10624 decal->color4f[1][3] = 1;
10625 decal->color4f[2][0] = c2[0];
10626 decal->color4f[2][1] = c2[1];
10627 decal->color4f[2][2] = c2[2];
10628 decal->color4f[2][3] = 1;
10629 decal->vertex3f[0][0] = v0[0];
10630 decal->vertex3f[0][1] = v0[1];
10631 decal->vertex3f[0][2] = v0[2];
10632 decal->vertex3f[1][0] = v1[0];
10633 decal->vertex3f[1][1] = v1[1];
10634 decal->vertex3f[1][2] = v1[2];
10635 decal->vertex3f[2][0] = v2[0];
10636 decal->vertex3f[2][1] = v2[1];
10637 decal->vertex3f[2][2] = v2[2];
10638 decal->texcoord2f[0][0] = t0[0];
10639 decal->texcoord2f[0][1] = t0[1];
10640 decal->texcoord2f[1][0] = t1[0];
10641 decal->texcoord2f[1][1] = t1[1];
10642 decal->texcoord2f[2][0] = t2[0];
10643 decal->texcoord2f[2][1] = t2[1];
10644 TriangleNormal(v0, v1, v2, decal->plane);
10645 VectorNormalize(decal->plane);
10646 decal->plane[3] = DotProduct(v0, decal->plane);
10649 extern cvar_t cl_decals_bias;
10650 extern cvar_t cl_decals_models;
10651 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10652 // baseparms, parms, temps
10653 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)
10658 const float *vertex3f;
10659 const float *normal3f;
10661 float points[2][9][3];
10668 e = rsurface.modelelement3i + 3*triangleindex;
10670 vertex3f = rsurface.modelvertex3f;
10671 normal3f = rsurface.modelnormal3f;
10675 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10677 index = 3*e[cornerindex];
10678 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10683 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10685 index = 3*e[cornerindex];
10686 VectorCopy(vertex3f + index, v[cornerindex]);
10691 //TriangleNormal(v[0], v[1], v[2], normal);
10692 //if (DotProduct(normal, localnormal) < 0.0f)
10694 // clip by each of the box planes formed from the projection matrix
10695 // if anything survives, we emit the decal
10696 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]);
10699 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]);
10702 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]);
10705 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]);
10708 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]);
10711 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]);
10714 // some part of the triangle survived, so we have to accept it...
10717 // dynamic always uses the original triangle
10719 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10721 index = 3*e[cornerindex];
10722 VectorCopy(vertex3f + index, v[cornerindex]);
10725 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10727 // convert vertex positions to texcoords
10728 Matrix4x4_Transform(projection, v[cornerindex], temp);
10729 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10730 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10731 // calculate distance fade from the projection origin
10732 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10733 f = bound(0.0f, f, 1.0f);
10734 c[cornerindex][0] = r * f;
10735 c[cornerindex][1] = g * f;
10736 c[cornerindex][2] = b * f;
10737 c[cornerindex][3] = 1.0f;
10738 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10741 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);
10743 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10744 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);
10746 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)
10748 matrix4x4_t projection;
10749 decalsystem_t *decalsystem;
10752 const msurface_t *surface;
10753 const msurface_t *surfaces;
10754 const int *surfacelist;
10755 const texture_t *texture;
10757 int numsurfacelist;
10758 int surfacelistindex;
10761 float localorigin[3];
10762 float localnormal[3];
10763 float localmins[3];
10764 float localmaxs[3];
10767 float planes[6][4];
10770 int bih_triangles_count;
10771 int bih_triangles[256];
10772 int bih_surfaces[256];
10774 decalsystem = &ent->decalsystem;
10775 model = ent->model;
10776 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10778 R_DecalSystem_Reset(&ent->decalsystem);
10782 if (!model->brush.data_leafs && !cl_decals_models.integer)
10784 if (decalsystem->model)
10785 R_DecalSystem_Reset(decalsystem);
10789 if (decalsystem->model != model)
10790 R_DecalSystem_Reset(decalsystem);
10791 decalsystem->model = model;
10793 RSurf_ActiveModelEntity(ent, true, false, false);
10795 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10796 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10797 VectorNormalize(localnormal);
10798 localsize = worldsize*rsurface.inversematrixscale;
10799 localmins[0] = localorigin[0] - localsize;
10800 localmins[1] = localorigin[1] - localsize;
10801 localmins[2] = localorigin[2] - localsize;
10802 localmaxs[0] = localorigin[0] + localsize;
10803 localmaxs[1] = localorigin[1] + localsize;
10804 localmaxs[2] = localorigin[2] + localsize;
10806 //VectorCopy(localnormal, planes[4]);
10807 //VectorVectors(planes[4], planes[2], planes[0]);
10808 AnglesFromVectors(angles, localnormal, NULL, false);
10809 AngleVectors(angles, planes[0], planes[2], planes[4]);
10810 VectorNegate(planes[0], planes[1]);
10811 VectorNegate(planes[2], planes[3]);
10812 VectorNegate(planes[4], planes[5]);
10813 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10814 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10815 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10816 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10817 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10818 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10823 matrix4x4_t forwardprojection;
10824 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10825 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10830 float projectionvector[4][3];
10831 VectorScale(planes[0], ilocalsize, projectionvector[0]);
10832 VectorScale(planes[2], ilocalsize, projectionvector[1]);
10833 VectorScale(planes[4], ilocalsize, projectionvector[2]);
10834 projectionvector[0][0] = planes[0][0] * ilocalsize;
10835 projectionvector[0][1] = planes[1][0] * ilocalsize;
10836 projectionvector[0][2] = planes[2][0] * ilocalsize;
10837 projectionvector[1][0] = planes[0][1] * ilocalsize;
10838 projectionvector[1][1] = planes[1][1] * ilocalsize;
10839 projectionvector[1][2] = planes[2][1] * ilocalsize;
10840 projectionvector[2][0] = planes[0][2] * ilocalsize;
10841 projectionvector[2][1] = planes[1][2] * ilocalsize;
10842 projectionvector[2][2] = planes[2][2] * ilocalsize;
10843 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10844 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10845 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10846 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10850 dynamic = model->surfmesh.isanimated;
10851 numsurfacelist = model->nummodelsurfaces;
10852 surfacelist = model->sortedmodelsurfaces;
10853 surfaces = model->data_surfaces;
10856 bih_triangles_count = -1;
10859 if(model->render_bih.numleafs)
10860 bih = &model->render_bih;
10861 else if(model->collision_bih.numleafs)
10862 bih = &model->collision_bih;
10865 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10866 if(bih_triangles_count == 0)
10868 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10870 if(bih_triangles_count > 0)
10872 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10874 surfaceindex = bih_surfaces[triangleindex];
10875 surface = surfaces + surfaceindex;
10876 texture = surface->texture;
10877 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10879 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10881 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10886 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10888 surfaceindex = surfacelist[surfacelistindex];
10889 surface = surfaces + surfaceindex;
10890 // check cull box first because it rejects more than any other check
10891 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10893 // skip transparent surfaces
10894 texture = surface->texture;
10895 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10897 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10899 numtriangles = surface->num_triangles;
10900 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10901 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10906 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10907 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)
10909 int renderentityindex;
10910 float worldmins[3];
10911 float worldmaxs[3];
10912 entity_render_t *ent;
10914 if (!cl_decals_newsystem.integer)
10917 worldmins[0] = worldorigin[0] - worldsize;
10918 worldmins[1] = worldorigin[1] - worldsize;
10919 worldmins[2] = worldorigin[2] - worldsize;
10920 worldmaxs[0] = worldorigin[0] + worldsize;
10921 worldmaxs[1] = worldorigin[1] + worldsize;
10922 worldmaxs[2] = worldorigin[2] + worldsize;
10924 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10926 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10928 ent = r_refdef.scene.entities[renderentityindex];
10929 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10932 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10936 typedef struct r_decalsystem_splatqueue_s
10938 vec3_t worldorigin;
10939 vec3_t worldnormal;
10945 r_decalsystem_splatqueue_t;
10947 int r_decalsystem_numqueued = 0;
10948 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10950 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)
10952 r_decalsystem_splatqueue_t *queue;
10954 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10957 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10958 VectorCopy(worldorigin, queue->worldorigin);
10959 VectorCopy(worldnormal, queue->worldnormal);
10960 Vector4Set(queue->color, r, g, b, a);
10961 Vector4Set(queue->tcrange, s1, t1, s2, t2);
10962 queue->worldsize = worldsize;
10963 queue->decalsequence = cl.decalsequence++;
10966 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10969 r_decalsystem_splatqueue_t *queue;
10971 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10972 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);
10973 r_decalsystem_numqueued = 0;
10976 extern cvar_t cl_decals_max;
10977 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10980 decalsystem_t *decalsystem = &ent->decalsystem;
10987 if (!decalsystem->numdecals)
10990 if (r_showsurfaces.integer)
10993 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10995 R_DecalSystem_Reset(decalsystem);
10999 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11000 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11002 if (decalsystem->lastupdatetime)
11003 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11006 decalsystem->lastupdatetime = r_refdef.scene.time;
11007 decal = decalsystem->decals;
11008 numdecals = decalsystem->numdecals;
11010 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11012 if (decal->color4f[0][3])
11014 decal->lived += frametime;
11015 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11017 memset(decal, 0, sizeof(*decal));
11018 if (decalsystem->freedecal > i)
11019 decalsystem->freedecal = i;
11023 decal = decalsystem->decals;
11024 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11027 // collapse the array by shuffling the tail decals into the gaps
11030 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11031 decalsystem->freedecal++;
11032 if (decalsystem->freedecal == numdecals)
11034 decal[decalsystem->freedecal] = decal[--numdecals];
11037 decalsystem->numdecals = numdecals;
11039 if (numdecals <= 0)
11041 // if there are no decals left, reset decalsystem
11042 R_DecalSystem_Reset(decalsystem);
11046 extern skinframe_t *decalskinframe;
11047 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11050 decalsystem_t *decalsystem = &ent->decalsystem;
11059 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11062 numdecals = decalsystem->numdecals;
11066 if (r_showsurfaces.integer)
11069 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11071 R_DecalSystem_Reset(decalsystem);
11075 // if the model is static it doesn't matter what value we give for
11076 // wantnormals and wanttangents, so this logic uses only rules applicable
11077 // to a model, knowing that they are meaningless otherwise
11078 if (ent == r_refdef.scene.worldentity)
11079 RSurf_ActiveWorldEntity();
11081 RSurf_ActiveModelEntity(ent, false, false, false);
11083 decalsystem->lastupdatetime = r_refdef.scene.time;
11084 decal = decalsystem->decals;
11086 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11088 // update vertex positions for animated models
11089 v3f = decalsystem->vertex3f;
11090 c4f = decalsystem->color4f;
11091 t2f = decalsystem->texcoord2f;
11092 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11094 if (!decal->color4f[0][3])
11097 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11101 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11104 // update color values for fading decals
11105 if (decal->lived >= cl_decals_time.value)
11106 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11110 c4f[ 0] = decal->color4f[0][0] * alpha;
11111 c4f[ 1] = decal->color4f[0][1] * alpha;
11112 c4f[ 2] = decal->color4f[0][2] * alpha;
11114 c4f[ 4] = decal->color4f[1][0] * alpha;
11115 c4f[ 5] = decal->color4f[1][1] * alpha;
11116 c4f[ 6] = decal->color4f[1][2] * alpha;
11118 c4f[ 8] = decal->color4f[2][0] * alpha;
11119 c4f[ 9] = decal->color4f[2][1] * alpha;
11120 c4f[10] = decal->color4f[2][2] * alpha;
11123 t2f[0] = decal->texcoord2f[0][0];
11124 t2f[1] = decal->texcoord2f[0][1];
11125 t2f[2] = decal->texcoord2f[1][0];
11126 t2f[3] = decal->texcoord2f[1][1];
11127 t2f[4] = decal->texcoord2f[2][0];
11128 t2f[5] = decal->texcoord2f[2][1];
11130 // update vertex positions for animated models
11131 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11133 e = rsurface.modelelement3i + 3*decal->triangleindex;
11134 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11135 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11136 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11140 VectorCopy(decal->vertex3f[0], v3f);
11141 VectorCopy(decal->vertex3f[1], v3f + 3);
11142 VectorCopy(decal->vertex3f[2], v3f + 6);
11145 if (r_refdef.fogenabled)
11147 alpha = RSurf_FogVertex(v3f);
11148 VectorScale(c4f, alpha, c4f);
11149 alpha = RSurf_FogVertex(v3f + 3);
11150 VectorScale(c4f + 4, alpha, c4f + 4);
11151 alpha = RSurf_FogVertex(v3f + 6);
11152 VectorScale(c4f + 8, alpha, c4f + 8);
11163 r_refdef.stats.drawndecals += numtris;
11165 // now render the decals all at once
11166 // (this assumes they all use one particle font texture!)
11167 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);
11168 // R_Mesh_ResetTextureState();
11169 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11170 GL_DepthMask(false);
11171 GL_DepthRange(0, 1);
11172 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11173 GL_DepthTest(true);
11174 GL_CullFace(GL_NONE);
11175 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11176 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false);
11177 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11181 static void R_DrawModelDecals(void)
11185 // fade faster when there are too many decals
11186 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11187 for (i = 0;i < r_refdef.scene.numentities;i++)
11188 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11190 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11191 for (i = 0;i < r_refdef.scene.numentities;i++)
11192 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11193 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11195 R_DecalSystem_ApplySplatEntitiesQueue();
11197 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11198 for (i = 0;i < r_refdef.scene.numentities;i++)
11199 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11201 r_refdef.stats.totaldecals += numdecals;
11203 if (r_showsurfaces.integer)
11206 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11208 for (i = 0;i < r_refdef.scene.numentities;i++)
11210 if (!r_refdef.viewcache.entityvisible[i])
11212 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11213 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11217 extern cvar_t mod_collision_bih;
11218 void R_DrawDebugModel(void)
11220 entity_render_t *ent = rsurface.entity;
11221 int i, j, k, l, flagsmask;
11222 const msurface_t *surface;
11223 dp_model_t *model = ent->model;
11226 if (!sv.active && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11229 if (r_showoverdraw.value > 0)
11231 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11232 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11233 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
11234 GL_DepthTest(false);
11235 GL_DepthMask(false);
11236 GL_DepthRange(0, 1);
11237 GL_BlendFunc(GL_ONE, GL_ONE);
11238 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11240 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11242 rsurface.texture = R_GetCurrentTexture(surface->texture);
11243 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11245 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11246 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11247 if (!rsurface.texture->currentlayers->depthmask)
11248 GL_Color(c, 0, 0, 1.0f);
11249 else if (ent == r_refdef.scene.worldentity)
11250 GL_Color(c, c, c, 1.0f);
11252 GL_Color(0, c, 0, 1.0f);
11253 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11257 rsurface.texture = NULL;
11260 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11262 // R_Mesh_ResetTextureState();
11263 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
11264 GL_DepthRange(0, 1);
11265 GL_DepthTest(!r_showdisabledepthtest.integer);
11266 GL_DepthMask(false);
11267 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11269 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11273 qboolean cullbox = ent == r_refdef.scene.worldentity;
11274 const q3mbrush_t *brush;
11275 const bih_t *bih = &model->collision_bih;
11276 const bih_leaf_t *bihleaf;
11277 float vertex3f[3][3];
11278 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11280 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11282 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11284 switch (bihleaf->type)
11287 brush = model->brush.data_brushes + bihleaf->itemindex;
11288 if (brush->colbrushf && brush->colbrushf->numtriangles)
11290 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);
11291 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11292 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11295 case BIH_COLLISIONTRIANGLE:
11296 triangleindex = bihleaf->itemindex;
11297 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11298 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11299 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11300 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);
11301 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11302 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11304 case BIH_RENDERTRIANGLE:
11305 triangleindex = bihleaf->itemindex;
11306 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11307 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11308 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11309 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);
11310 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11311 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11317 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11319 if (r_showtris.integer && qglPolygonMode)
11321 if (r_showdisabledepthtest.integer)
11323 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11324 GL_DepthMask(false);
11328 GL_BlendFunc(GL_ONE, GL_ZERO);
11329 GL_DepthMask(true);
11331 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11332 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11334 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11336 rsurface.texture = R_GetCurrentTexture(surface->texture);
11337 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11339 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11340 if (!rsurface.texture->currentlayers->depthmask)
11341 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11342 else if (ent == r_refdef.scene.worldentity)
11343 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11345 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11346 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11350 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11351 rsurface.texture = NULL;
11354 if (r_shownormals.value != 0 && qglBegin)
11356 if (r_showdisabledepthtest.integer)
11358 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11359 GL_DepthMask(false);
11363 GL_BlendFunc(GL_ONE, GL_ZERO);
11364 GL_DepthMask(true);
11366 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11368 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11370 rsurface.texture = R_GetCurrentTexture(surface->texture);
11371 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11373 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11374 qglBegin(GL_LINES);
11375 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11377 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11379 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11380 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11381 qglVertex3f(v[0], v[1], v[2]);
11382 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11383 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11384 qglVertex3f(v[0], v[1], v[2]);
11387 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11389 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11391 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11392 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11393 qglVertex3f(v[0], v[1], v[2]);
11394 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11395 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11396 qglVertex3f(v[0], v[1], v[2]);
11399 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11401 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11403 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11404 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11405 qglVertex3f(v[0], v[1], v[2]);
11406 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11407 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11408 qglVertex3f(v[0], v[1], v[2]);
11411 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11413 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11415 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11416 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11417 qglVertex3f(v[0], v[1], v[2]);
11418 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11419 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11420 qglVertex3f(v[0], v[1], v[2]);
11427 rsurface.texture = NULL;
11431 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11432 int r_maxsurfacelist = 0;
11433 const msurface_t **r_surfacelist = NULL;
11434 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11436 int i, j, endj, flagsmask;
11437 dp_model_t *model = r_refdef.scene.worldmodel;
11438 msurface_t *surfaces;
11439 unsigned char *update;
11440 int numsurfacelist = 0;
11444 if (r_maxsurfacelist < model->num_surfaces)
11446 r_maxsurfacelist = model->num_surfaces;
11448 Mem_Free((msurface_t**)r_surfacelist);
11449 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11452 RSurf_ActiveWorldEntity();
11454 surfaces = model->data_surfaces;
11455 update = model->brushq1.lightmapupdateflags;
11457 // update light styles on this submodel
11458 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11460 model_brush_lightstyleinfo_t *style;
11461 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11463 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11465 int *list = style->surfacelist;
11466 style->value = r_refdef.scene.lightstylevalue[style->style];
11467 for (j = 0;j < style->numsurfaces;j++)
11468 update[list[j]] = true;
11473 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11477 R_DrawDebugModel();
11478 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11482 rsurface.lightmaptexture = NULL;
11483 rsurface.deluxemaptexture = NULL;
11484 rsurface.uselightmaptexture = false;
11485 rsurface.texture = NULL;
11486 rsurface.rtlight = NULL;
11487 numsurfacelist = 0;
11488 // add visible surfaces to draw list
11489 for (i = 0;i < model->nummodelsurfaces;i++)
11491 j = model->sortedmodelsurfaces[i];
11492 if (r_refdef.viewcache.world_surfacevisible[j])
11493 r_surfacelist[numsurfacelist++] = surfaces + j;
11495 // update lightmaps if needed
11496 if (model->brushq1.firstrender)
11498 model->brushq1.firstrender = false;
11499 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11501 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11505 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11506 if (r_refdef.viewcache.world_surfacevisible[j])
11508 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11510 // don't do anything if there were no surfaces
11511 if (!numsurfacelist)
11513 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11516 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11518 // add to stats if desired
11519 if (r_speeds.integer && !skysurfaces && !depthonly)
11521 r_refdef.stats.world_surfaces += numsurfacelist;
11522 for (j = 0;j < numsurfacelist;j++)
11523 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11526 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11529 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11531 int i, j, endj, flagsmask;
11532 dp_model_t *model = ent->model;
11533 msurface_t *surfaces;
11534 unsigned char *update;
11535 int numsurfacelist = 0;
11539 if (r_maxsurfacelist < model->num_surfaces)
11541 r_maxsurfacelist = model->num_surfaces;
11543 Mem_Free((msurface_t **)r_surfacelist);
11544 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11547 // if the model is static it doesn't matter what value we give for
11548 // wantnormals and wanttangents, so this logic uses only rules applicable
11549 // to a model, knowing that they are meaningless otherwise
11550 if (ent == r_refdef.scene.worldentity)
11551 RSurf_ActiveWorldEntity();
11552 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11553 RSurf_ActiveModelEntity(ent, false, false, false);
11555 RSurf_ActiveModelEntity(ent, true, true, true);
11556 else if (depthonly)
11558 switch (vid.renderpath)
11560 case RENDERPATH_GL20:
11561 case RENDERPATH_D3D9:
11562 case RENDERPATH_D3D10:
11563 case RENDERPATH_D3D11:
11564 case RENDERPATH_SOFT:
11565 case RENDERPATH_GLES2:
11566 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11568 case RENDERPATH_GL11:
11569 case RENDERPATH_GL13:
11570 case RENDERPATH_GLES1:
11571 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11577 switch (vid.renderpath)
11579 case RENDERPATH_GL20:
11580 case RENDERPATH_D3D9:
11581 case RENDERPATH_D3D10:
11582 case RENDERPATH_D3D11:
11583 case RENDERPATH_SOFT:
11584 case RENDERPATH_GLES2:
11585 RSurf_ActiveModelEntity(ent, true, true, false);
11587 case RENDERPATH_GL11:
11588 case RENDERPATH_GL13:
11589 case RENDERPATH_GLES1:
11590 RSurf_ActiveModelEntity(ent, true, false, false);
11595 surfaces = model->data_surfaces;
11596 update = model->brushq1.lightmapupdateflags;
11598 // update light styles
11599 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11601 model_brush_lightstyleinfo_t *style;
11602 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11604 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11606 int *list = style->surfacelist;
11607 style->value = r_refdef.scene.lightstylevalue[style->style];
11608 for (j = 0;j < style->numsurfaces;j++)
11609 update[list[j]] = true;
11614 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11618 R_DrawDebugModel();
11619 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11623 rsurface.lightmaptexture = NULL;
11624 rsurface.deluxemaptexture = NULL;
11625 rsurface.uselightmaptexture = false;
11626 rsurface.texture = NULL;
11627 rsurface.rtlight = NULL;
11628 numsurfacelist = 0;
11629 // add visible surfaces to draw list
11630 for (i = 0;i < model->nummodelsurfaces;i++)
11631 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11632 // don't do anything if there were no surfaces
11633 if (!numsurfacelist)
11635 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11638 // update lightmaps if needed
11642 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11647 R_BuildLightMap(ent, surfaces + j);
11652 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11654 R_BuildLightMap(ent, surfaces + j);
11655 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11657 // add to stats if desired
11658 if (r_speeds.integer && !skysurfaces && !depthonly)
11660 r_refdef.stats.entities_surfaces += numsurfacelist;
11661 for (j = 0;j < numsurfacelist;j++)
11662 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11665 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11668 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11670 static texture_t texture;
11671 static msurface_t surface;
11672 const msurface_t *surfacelist = &surface;
11674 // fake enough texture and surface state to render this geometry
11676 texture.update_lastrenderframe = -1; // regenerate this texture
11677 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11678 texture.currentskinframe = skinframe;
11679 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11680 texture.offsetmapping = OFFSETMAPPING_OFF;
11681 texture.offsetscale = 1;
11682 texture.specularscalemod = 1;
11683 texture.specularpowermod = 1;
11685 surface.texture = &texture;
11686 surface.num_triangles = numtriangles;
11687 surface.num_firsttriangle = firsttriangle;
11688 surface.num_vertices = numvertices;
11689 surface.num_firstvertex = firstvertex;
11692 rsurface.texture = R_GetCurrentTexture(surface.texture);
11693 rsurface.lightmaptexture = NULL;
11694 rsurface.deluxemaptexture = NULL;
11695 rsurface.uselightmaptexture = false;
11696 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11699 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)
11701 static msurface_t surface;
11702 const msurface_t *surfacelist = &surface;
11704 // fake enough texture and surface state to render this geometry
11705 surface.texture = texture;
11706 surface.num_triangles = numtriangles;
11707 surface.num_firsttriangle = firsttriangle;
11708 surface.num_vertices = numvertices;
11709 surface.num_firstvertex = firstvertex;
11712 rsurface.texture = R_GetCurrentTexture(surface.texture);
11713 rsurface.lightmaptexture = NULL;
11714 rsurface.deluxemaptexture = NULL;
11715 rsurface.uselightmaptexture = false;
11716 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);