2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 #include "cl_dyntexture.h"
30 #include "dpsoftrast.h"
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
37 mempool_t *r_main_mempool;
38 rtexturepool_t *r_main_texturepool;
40 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
42 static qboolean r_loadnormalmap;
43 static qboolean r_loadgloss;
45 static qboolean r_loaddds;
46 static qboolean r_savedds;
53 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
55 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
56 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
57 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
58 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
59 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
60 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
62 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
63 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
64 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
65 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
66 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
68 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
69 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
70 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
71 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
72 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
73 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
74 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
75 cvar_t r_transparent_alphatocoverage = {0, "r_transparent_alphatocoverage", "0", "enables alpha-to-coverage antialiasing technique on alphatest surfaces, this is not yet finished as multisampling is not used"};
76 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
77 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
78 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
79 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
80 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
81 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
82 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
83 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
84 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
85 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
86 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
87 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
88 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
89 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
90 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
91 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
92 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
93 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
94 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
95 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
96 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
97 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
98 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
99 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
101 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
102 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
103 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
105 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
106 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
107 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
108 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
109 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
110 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
111 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
112 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
113 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
114 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
115 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
116 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
117 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
118 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
119 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
120 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
121 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
122 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
123 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
124 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
125 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
126 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
128 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
129 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
130 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
131 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
132 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
133 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
134 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
135 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
137 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
138 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
140 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
141 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
142 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
144 cvar_t r_viewfbo = {CVAR_SAVE, "r_viewfbo", "0", "enables use of an 8bit (1) or 16bit (2) or 32bit (3) per component float framebuffer render, which may be at a different resolution than the video mode"};
145 cvar_t r_viewscale = {CVAR_SAVE, "r_viewscale", "1", "scaling factor for resolution of the fbo rendering method, must be > 0, can be above 1 for a costly antialiasing behavior, typical values are 0.5 for 1/4th as many pixels rendered, or 1 for normal rendering"};
146 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
147 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
148 cvar_t r_viewscale_fpsscaling_multiply = {CVAR_SAVE, "r_viewscale_fpsscaling_multiply", "5", "adjust quality up or down by the frametime difference from 1.0/target, multiplied by this factor"};
149 cvar_t r_viewscale_fpsscaling_stepsize = {CVAR_SAVE, "r_viewscale_fpsscaling_stepsize", "0.01", "smallest adjustment to hit the target framerate (this value prevents minute oscillations)"};
150 cvar_t r_viewscale_fpsscaling_stepmax = {CVAR_SAVE, "r_viewscale_fpsscaling_stepmax", "1.00", "largest adjustment to hit the target framerate (this value prevents wild overshooting of the estimate)"};
151 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
153 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
154 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
155 cvar_t r_glsl_offsetmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_steps", "2", "offset mapping steps (note: too high values may be not supported by your GPU)"};
156 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
157 cvar_t r_glsl_offsetmapping_reliefmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_steps", "10", "relief mapping steps (note: too high values may be not supported by your GPU)"};
158 cvar_t r_glsl_offsetmapping_reliefmapping_refinesteps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_refinesteps", "5", "relief mapping refine steps (these are a binary search executed as the last step as given by r_glsl_offsetmapping_reliefmapping_steps)"};
159 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
160 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
161 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
162 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
163 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
164 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
165 cvar_t r_glsl_postprocess_uservec1_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec1_enable", "1", "enables postprocessing uservec1 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
166 cvar_t r_glsl_postprocess_uservec2_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec2_enable", "1", "enables postprocessing uservec2 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
167 cvar_t r_glsl_postprocess_uservec3_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec3_enable", "1", "enables postprocessing uservec3 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
168 cvar_t r_glsl_postprocess_uservec4_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec4_enable", "1", "enables postprocessing uservec4 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
170 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
171 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
172 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
173 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
174 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
175 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
176 cvar_t r_water_lowquality = {0, "r_water_lowquality", "0", "special option to accelerate water rendering, 1 disables shadows and particles, 2 disables all dynamic lights"};
178 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
179 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
180 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
181 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
183 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
184 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
185 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
186 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
187 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
188 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
189 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
191 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
192 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
193 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
194 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivalent to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
195 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
196 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
197 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
198 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
199 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
200 cvar_t r_hdr_irisadaptation_fade = {CVAR_SAVE, "r_hdr_irisadaptation_fade", "1", "fade rate at which value adjusts"};
202 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
204 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
206 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
208 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
210 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
211 cvar_t r_glsl_saturation_redcompensate = {CVAR_SAVE, "r_glsl_saturation_redcompensate", "0", "a 'vampire sight' addition to desaturation effect, does compensation for red color, r_glsl_restart is required"};
213 cvar_t r_glsl_vertextextureblend_usebothalphas = {CVAR_SAVE, "r_glsl_vertextextureblend_usebothalphas", "0", "use both alpha layers on vertex blended surfaces, each alpha layer sets amount of 'blend leak' on another layer."};
215 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "0.5", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
217 extern cvar_t v_glslgamma;
219 extern qboolean v_flipped_state;
221 static struct r_bloomstate_s
226 int bloomwidth, bloomheight;
228 textype_t texturetype;
229 int viewfbo; // used to check if r_viewfbo cvar has changed
231 int fbo_framebuffer; // non-zero if r_viewfbo is enabled and working
232 rtexture_t *texture_framebuffercolor; // non-NULL if fbo_screen is non-zero
233 rtexture_t *texture_framebufferdepth; // non-NULL if fbo_screen is non-zero
235 int screentexturewidth, screentextureheight;
236 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
238 int bloomtexturewidth, bloomtextureheight;
239 rtexture_t *texture_bloom;
241 // arrays for rendering the screen passes
242 float screentexcoord2f[8];
243 float bloomtexcoord2f[8];
244 float offsettexcoord2f[8];
246 r_viewport_t viewport;
250 r_waterstate_t r_waterstate;
252 /// shadow volume bsp struct with automatically growing nodes buffer
255 rtexture_t *r_texture_blanknormalmap;
256 rtexture_t *r_texture_white;
257 rtexture_t *r_texture_grey128;
258 rtexture_t *r_texture_black;
259 rtexture_t *r_texture_notexture;
260 rtexture_t *r_texture_whitecube;
261 rtexture_t *r_texture_normalizationcube;
262 rtexture_t *r_texture_fogattenuation;
263 rtexture_t *r_texture_fogheighttexture;
264 rtexture_t *r_texture_gammaramps;
265 unsigned int r_texture_gammaramps_serial;
266 //rtexture_t *r_texture_fogintensity;
267 rtexture_t *r_texture_reflectcube;
269 // TODO: hash lookups?
270 typedef struct cubemapinfo_s
277 int r_texture_numcubemaps;
278 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
280 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
281 unsigned int r_numqueries;
282 unsigned int r_maxqueries;
284 typedef struct r_qwskincache_s
286 char name[MAX_QPATH];
287 skinframe_t *skinframe;
291 static r_qwskincache_t *r_qwskincache;
292 static int r_qwskincache_size;
294 /// vertex coordinates for a quad that covers the screen exactly
295 extern const float r_screenvertex3f[12];
296 extern const float r_d3dscreenvertex3f[12];
297 const float r_screenvertex3f[12] =
304 const float r_d3dscreenvertex3f[12] =
312 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
315 for (i = 0;i < verts;i++)
326 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
329 for (i = 0;i < verts;i++)
339 // FIXME: move this to client?
342 if (gamemode == GAME_NEHAHRA)
344 Cvar_Set("gl_fogenable", "0");
345 Cvar_Set("gl_fogdensity", "0.2");
346 Cvar_Set("gl_fogred", "0.3");
347 Cvar_Set("gl_foggreen", "0.3");
348 Cvar_Set("gl_fogblue", "0.3");
350 r_refdef.fog_density = 0;
351 r_refdef.fog_red = 0;
352 r_refdef.fog_green = 0;
353 r_refdef.fog_blue = 0;
354 r_refdef.fog_alpha = 1;
355 r_refdef.fog_start = 0;
356 r_refdef.fog_end = 16384;
357 r_refdef.fog_height = 1<<30;
358 r_refdef.fog_fadedepth = 128;
359 memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
362 static void R_BuildBlankTextures(void)
364 unsigned char data[4];
365 data[2] = 128; // normal X
366 data[1] = 128; // normal Y
367 data[0] = 255; // normal Z
368 data[3] = 128; // height
369 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
374 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
379 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
384 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
387 static void R_BuildNoTexture(void)
390 unsigned char pix[16][16][4];
391 // this makes a light grey/dark grey checkerboard texture
392 for (y = 0;y < 16;y++)
394 for (x = 0;x < 16;x++)
396 if ((y < 8) ^ (x < 8))
412 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
415 static void R_BuildWhiteCube(void)
417 unsigned char data[6*1*1*4];
418 memset(data, 255, sizeof(data));
419 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
422 static void R_BuildNormalizationCube(void)
426 vec_t s, t, intensity;
429 data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
430 for (side = 0;side < 6;side++)
432 for (y = 0;y < NORMSIZE;y++)
434 for (x = 0;x < NORMSIZE;x++)
436 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
437 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
472 intensity = 127.0f / sqrt(DotProduct(v, v));
473 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
474 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
475 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
476 data[((side*64+y)*64+x)*4+3] = 255;
480 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
484 static void R_BuildFogTexture(void)
488 unsigned char data1[FOGWIDTH][4];
489 //unsigned char data2[FOGWIDTH][4];
492 r_refdef.fogmasktable_start = r_refdef.fog_start;
493 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
494 r_refdef.fogmasktable_range = r_refdef.fogrange;
495 r_refdef.fogmasktable_density = r_refdef.fog_density;
497 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
498 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
500 d = (x * r - r_refdef.fogmasktable_start);
501 if(developer_extra.integer)
502 Con_DPrintf("%f ", d);
504 if (r_fog_exp2.integer)
505 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
507 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
508 if(developer_extra.integer)
509 Con_DPrintf(" : %f ", alpha);
510 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
511 if(developer_extra.integer)
512 Con_DPrintf(" = %f\n", alpha);
513 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
516 for (x = 0;x < FOGWIDTH;x++)
518 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
523 //data2[x][0] = 255 - b;
524 //data2[x][1] = 255 - b;
525 //data2[x][2] = 255 - b;
528 if (r_texture_fogattenuation)
530 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
531 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
535 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
536 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
540 static void R_BuildFogHeightTexture(void)
542 unsigned char *inpixels;
550 strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
551 if (r_refdef.fogheighttexturename[0])
552 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
555 r_refdef.fog_height_tablesize = 0;
556 if (r_texture_fogheighttexture)
557 R_FreeTexture(r_texture_fogheighttexture);
558 r_texture_fogheighttexture = NULL;
559 if (r_refdef.fog_height_table2d)
560 Mem_Free(r_refdef.fog_height_table2d);
561 r_refdef.fog_height_table2d = NULL;
562 if (r_refdef.fog_height_table1d)
563 Mem_Free(r_refdef.fog_height_table1d);
564 r_refdef.fog_height_table1d = NULL;
568 r_refdef.fog_height_tablesize = size;
569 r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
570 r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
571 memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
573 // LordHavoc: now the magic - what is that table2d for? it is a cooked
574 // average fog color table accounting for every fog layer between a point
575 // and the camera. (Note: attenuation is handled separately!)
576 for (y = 0;y < size;y++)
578 for (x = 0;x < size;x++)
584 for (j = x;j <= y;j++)
586 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
592 for (j = x;j >= y;j--)
594 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
599 r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
600 r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
601 r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
602 r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
605 r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
608 //=======================================================================================================================================================
610 static const char *builtinshaderstring =
611 #include "shader_glsl.h"
614 const char *builtinhlslshaderstring =
615 #include "shader_hlsl.h"
618 char *glslshaderstring = NULL;
619 char *hlslshaderstring = NULL;
621 //=======================================================================================================================================================
623 typedef struct shaderpermutationinfo_s
628 shaderpermutationinfo_t;
630 typedef struct shadermodeinfo_s
632 const char *vertexfilename;
633 const char *geometryfilename;
634 const char *fragmentfilename;
640 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
641 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
643 {"#define USEDIFFUSE\n", " diffuse"},
644 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
645 {"#define USEVIEWTINT\n", " viewtint"},
646 {"#define USECOLORMAPPING\n", " colormapping"},
647 {"#define USESATURATION\n", " saturation"},
648 {"#define USEFOGINSIDE\n", " foginside"},
649 {"#define USEFOGOUTSIDE\n", " fogoutside"},
650 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
651 {"#define USEFOGALPHAHACK\n", " fogalphahack"},
652 {"#define USEGAMMARAMPS\n", " gammaramps"},
653 {"#define USECUBEFILTER\n", " cubefilter"},
654 {"#define USEGLOW\n", " glow"},
655 {"#define USEBLOOM\n", " bloom"},
656 {"#define USESPECULAR\n", " specular"},
657 {"#define USEPOSTPROCESSING\n", " postprocessing"},
658 {"#define USEREFLECTION\n", " reflection"},
659 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
660 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
661 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
662 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
663 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
664 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
665 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
666 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
667 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
668 {"#define USEALPHAKILL\n", " alphakill"},
669 {"#define USEREFLECTCUBE\n", " reflectcube"},
670 {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
671 {"#define USEBOUNCEGRID\n", " bouncegrid"},
672 {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
675 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
676 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
678 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
679 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
680 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
681 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
682 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
683 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
684 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
685 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
686 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
687 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
688 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
689 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
690 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
691 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
692 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
693 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
696 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
698 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
699 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
700 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
701 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
702 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
703 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
704 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
705 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
706 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
707 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
708 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
709 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
710 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
711 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
712 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
713 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
716 struct r_glsl_permutation_s;
717 typedef struct r_glsl_permutation_s
720 struct r_glsl_permutation_s *hashnext;
722 unsigned int permutation;
724 /// indicates if we have tried compiling this permutation already
726 /// 0 if compilation failed
728 // texture units assigned to each detected uniform
729 int tex_Texture_First;
730 int tex_Texture_Second;
731 int tex_Texture_GammaRamps;
732 int tex_Texture_Normal;
733 int tex_Texture_Color;
734 int tex_Texture_Gloss;
735 int tex_Texture_Glow;
736 int tex_Texture_SecondaryNormal;
737 int tex_Texture_SecondaryColor;
738 int tex_Texture_SecondaryGloss;
739 int tex_Texture_SecondaryGlow;
740 int tex_Texture_Pants;
741 int tex_Texture_Shirt;
742 int tex_Texture_FogHeightTexture;
743 int tex_Texture_FogMask;
744 int tex_Texture_Lightmap;
745 int tex_Texture_Deluxemap;
746 int tex_Texture_Attenuation;
747 int tex_Texture_Cube;
748 int tex_Texture_Refraction;
749 int tex_Texture_Reflection;
750 int tex_Texture_ShadowMap2D;
751 int tex_Texture_CubeProjection;
752 int tex_Texture_ScreenDepth;
753 int tex_Texture_ScreenNormalMap;
754 int tex_Texture_ScreenDiffuse;
755 int tex_Texture_ScreenSpecular;
756 int tex_Texture_ReflectMask;
757 int tex_Texture_ReflectCube;
758 int tex_Texture_BounceGrid;
759 /// locations of detected uniforms in program object, or -1 if not found
760 int loc_Texture_First;
761 int loc_Texture_Second;
762 int loc_Texture_GammaRamps;
763 int loc_Texture_Normal;
764 int loc_Texture_Color;
765 int loc_Texture_Gloss;
766 int loc_Texture_Glow;
767 int loc_Texture_SecondaryNormal;
768 int loc_Texture_SecondaryColor;
769 int loc_Texture_SecondaryGloss;
770 int loc_Texture_SecondaryGlow;
771 int loc_Texture_Pants;
772 int loc_Texture_Shirt;
773 int loc_Texture_FogHeightTexture;
774 int loc_Texture_FogMask;
775 int loc_Texture_Lightmap;
776 int loc_Texture_Deluxemap;
777 int loc_Texture_Attenuation;
778 int loc_Texture_Cube;
779 int loc_Texture_Refraction;
780 int loc_Texture_Reflection;
781 int loc_Texture_ShadowMap2D;
782 int loc_Texture_CubeProjection;
783 int loc_Texture_ScreenDepth;
784 int loc_Texture_ScreenNormalMap;
785 int loc_Texture_ScreenDiffuse;
786 int loc_Texture_ScreenSpecular;
787 int loc_Texture_ReflectMask;
788 int loc_Texture_ReflectCube;
789 int loc_Texture_BounceGrid;
791 int loc_BloomBlur_Parameters;
793 int loc_Color_Ambient;
794 int loc_Color_Diffuse;
795 int loc_Color_Specular;
799 int loc_DeferredColor_Ambient;
800 int loc_DeferredColor_Diffuse;
801 int loc_DeferredColor_Specular;
802 int loc_DeferredMod_Diffuse;
803 int loc_DeferredMod_Specular;
804 int loc_DistortScaleRefractReflect;
807 int loc_FogHeightFade;
809 int loc_FogPlaneViewDist;
810 int loc_FogRangeRecip;
813 int loc_LightPosition;
814 int loc_OffsetMapping_ScaleSteps;
816 int loc_ReflectColor;
817 int loc_ReflectFactor;
818 int loc_ReflectOffset;
819 int loc_RefractColor;
821 int loc_ScreenCenterRefractReflect;
822 int loc_ScreenScaleRefractReflect;
823 int loc_ScreenToDepth;
824 int loc_ShadowMap_Parameters;
825 int loc_ShadowMap_TextureScale;
826 int loc_SpecularPower;
831 int loc_ViewTintColor;
833 int loc_ModelToLight;
835 int loc_BackgroundTexMatrix;
836 int loc_ModelViewProjectionMatrix;
837 int loc_ModelViewMatrix;
838 int loc_PixelToScreenTexCoord;
839 int loc_ModelToReflectCube;
840 int loc_ShadowMapMatrix;
841 int loc_BloomColorSubtract;
842 int loc_NormalmapScrollBlend;
843 int loc_BounceGridMatrix;
844 int loc_BounceGridIntensity;
846 r_glsl_permutation_t;
848 #define SHADERPERMUTATION_HASHSIZE 256
851 // non-degradable "lightweight" shader parameters to keep the permutations simpler
852 // these can NOT degrade! only use for simple stuff
855 SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
856 SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
857 SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
858 SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
859 SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
860 SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5, ///< postprocess uservec4 is enabled
861 SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6 // use both alpha layers while blending materials, allows more advanced microblending
863 #define SHADERSTATICPARMS_COUNT 7
865 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
866 static int shaderstaticparms_count = 0;
868 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
869 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
870 qboolean R_CompileShader_CheckStaticParms(void)
872 static int r_compileshader_staticparms_save[1];
873 memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
874 memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
877 if (r_glsl_saturation_redcompensate.integer)
878 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
879 if (r_glsl_vertextextureblend_usebothalphas.integer)
880 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
881 if (r_shadow_glossexact.integer)
882 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
883 if (r_glsl_postprocess.integer)
885 if (r_glsl_postprocess_uservec1_enable.integer)
886 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
887 if (r_glsl_postprocess_uservec2_enable.integer)
888 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
889 if (r_glsl_postprocess_uservec3_enable.integer)
890 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
891 if (r_glsl_postprocess_uservec4_enable.integer)
892 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
894 return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
897 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
898 if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
899 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
901 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
902 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
904 shaderstaticparms_count = 0;
907 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
908 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
909 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
910 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
911 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
912 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
913 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
916 /// information about each possible shader permutation
917 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
918 /// currently selected permutation
919 r_glsl_permutation_t *r_glsl_permutation;
920 /// storage for permutations linked in the hash table
921 memexpandablearray_t r_glsl_permutationarray;
923 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
925 //unsigned int hashdepth = 0;
926 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
927 r_glsl_permutation_t *p;
928 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
930 if (p->mode == mode && p->permutation == permutation)
932 //if (hashdepth > 10)
933 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
938 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
940 p->permutation = permutation;
941 p->hashnext = r_glsl_permutationhash[mode][hashindex];
942 r_glsl_permutationhash[mode][hashindex] = p;
943 //if (hashdepth > 10)
944 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
948 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
951 if (!filename || !filename[0])
953 if (!strcmp(filename, "glsl/default.glsl"))
955 if (!glslshaderstring)
957 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
958 if (glslshaderstring)
959 Con_DPrintf("Loading shaders from file %s...\n", filename);
961 glslshaderstring = (char *)builtinshaderstring;
963 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
964 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
967 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
970 if (printfromdisknotice)
971 Con_DPrintf("from disk %s... ", filename);
977 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
981 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
982 char *vertexstring, *geometrystring, *fragmentstring;
983 char permutationname[256];
984 int vertstrings_count = 0;
985 int geomstrings_count = 0;
986 int fragstrings_count = 0;
987 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
988 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
989 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
996 permutationname[0] = 0;
997 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
998 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
999 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1001 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1003 // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1004 if(vid.support.gl20shaders130)
1006 vertstrings_list[vertstrings_count++] = "#version 130\n";
1007 geomstrings_list[geomstrings_count++] = "#version 130\n";
1008 fragstrings_list[fragstrings_count++] = "#version 130\n";
1009 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1010 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1011 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1014 // the first pretext is which type of shader to compile as
1015 // (later these will all be bound together as a program object)
1016 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1017 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1018 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1020 // the second pretext is the mode (for example a light source)
1021 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1022 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1023 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1024 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1026 // now add all the permutation pretexts
1027 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1029 if (permutation & (1<<i))
1031 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1032 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1033 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1034 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1038 // keep line numbers correct
1039 vertstrings_list[vertstrings_count++] = "\n";
1040 geomstrings_list[geomstrings_count++] = "\n";
1041 fragstrings_list[fragstrings_count++] = "\n";
1046 R_CompileShader_AddStaticParms(mode, permutation);
1047 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1048 vertstrings_count += shaderstaticparms_count;
1049 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1050 geomstrings_count += shaderstaticparms_count;
1051 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1052 fragstrings_count += shaderstaticparms_count;
1054 // now append the shader text itself
1055 vertstrings_list[vertstrings_count++] = vertexstring;
1056 geomstrings_list[geomstrings_count++] = geometrystring;
1057 fragstrings_list[fragstrings_count++] = fragmentstring;
1059 // if any sources were NULL, clear the respective list
1061 vertstrings_count = 0;
1062 if (!geometrystring)
1063 geomstrings_count = 0;
1064 if (!fragmentstring)
1065 fragstrings_count = 0;
1067 // compile the shader program
1068 if (vertstrings_count + geomstrings_count + fragstrings_count)
1069 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1073 qglUseProgram(p->program);CHECKGLERROR
1074 // look up all the uniform variable names we care about, so we don't
1075 // have to look them up every time we set them
1077 p->loc_Texture_First = qglGetUniformLocation(p->program, "Texture_First");
1078 p->loc_Texture_Second = qglGetUniformLocation(p->program, "Texture_Second");
1079 p->loc_Texture_GammaRamps = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1080 p->loc_Texture_Normal = qglGetUniformLocation(p->program, "Texture_Normal");
1081 p->loc_Texture_Color = qglGetUniformLocation(p->program, "Texture_Color");
1082 p->loc_Texture_Gloss = qglGetUniformLocation(p->program, "Texture_Gloss");
1083 p->loc_Texture_Glow = qglGetUniformLocation(p->program, "Texture_Glow");
1084 p->loc_Texture_SecondaryNormal = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1085 p->loc_Texture_SecondaryColor = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1086 p->loc_Texture_SecondaryGloss = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1087 p->loc_Texture_SecondaryGlow = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1088 p->loc_Texture_Pants = qglGetUniformLocation(p->program, "Texture_Pants");
1089 p->loc_Texture_Shirt = qglGetUniformLocation(p->program, "Texture_Shirt");
1090 p->loc_Texture_FogHeightTexture = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1091 p->loc_Texture_FogMask = qglGetUniformLocation(p->program, "Texture_FogMask");
1092 p->loc_Texture_Lightmap = qglGetUniformLocation(p->program, "Texture_Lightmap");
1093 p->loc_Texture_Deluxemap = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1094 p->loc_Texture_Attenuation = qglGetUniformLocation(p->program, "Texture_Attenuation");
1095 p->loc_Texture_Cube = qglGetUniformLocation(p->program, "Texture_Cube");
1096 p->loc_Texture_Refraction = qglGetUniformLocation(p->program, "Texture_Refraction");
1097 p->loc_Texture_Reflection = qglGetUniformLocation(p->program, "Texture_Reflection");
1098 p->loc_Texture_ShadowMap2D = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1099 p->loc_Texture_CubeProjection = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1100 p->loc_Texture_ScreenDepth = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1101 p->loc_Texture_ScreenNormalMap = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1102 p->loc_Texture_ScreenDiffuse = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1103 p->loc_Texture_ScreenSpecular = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1104 p->loc_Texture_ReflectMask = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1105 p->loc_Texture_ReflectCube = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1106 p->loc_Texture_BounceGrid = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1107 p->loc_Alpha = qglGetUniformLocation(p->program, "Alpha");
1108 p->loc_BloomBlur_Parameters = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1109 p->loc_ClientTime = qglGetUniformLocation(p->program, "ClientTime");
1110 p->loc_Color_Ambient = qglGetUniformLocation(p->program, "Color_Ambient");
1111 p->loc_Color_Diffuse = qglGetUniformLocation(p->program, "Color_Diffuse");
1112 p->loc_Color_Specular = qglGetUniformLocation(p->program, "Color_Specular");
1113 p->loc_Color_Glow = qglGetUniformLocation(p->program, "Color_Glow");
1114 p->loc_Color_Pants = qglGetUniformLocation(p->program, "Color_Pants");
1115 p->loc_Color_Shirt = qglGetUniformLocation(p->program, "Color_Shirt");
1116 p->loc_DeferredColor_Ambient = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1117 p->loc_DeferredColor_Diffuse = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1118 p->loc_DeferredColor_Specular = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1119 p->loc_DeferredMod_Diffuse = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1120 p->loc_DeferredMod_Specular = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1121 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1122 p->loc_EyePosition = qglGetUniformLocation(p->program, "EyePosition");
1123 p->loc_FogColor = qglGetUniformLocation(p->program, "FogColor");
1124 p->loc_FogHeightFade = qglGetUniformLocation(p->program, "FogHeightFade");
1125 p->loc_FogPlane = qglGetUniformLocation(p->program, "FogPlane");
1126 p->loc_FogPlaneViewDist = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1127 p->loc_FogRangeRecip = qglGetUniformLocation(p->program, "FogRangeRecip");
1128 p->loc_LightColor = qglGetUniformLocation(p->program, "LightColor");
1129 p->loc_LightDir = qglGetUniformLocation(p->program, "LightDir");
1130 p->loc_LightPosition = qglGetUniformLocation(p->program, "LightPosition");
1131 p->loc_OffsetMapping_ScaleSteps = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1132 p->loc_PixelSize = qglGetUniformLocation(p->program, "PixelSize");
1133 p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor");
1134 p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor");
1135 p->loc_ReflectOffset = qglGetUniformLocation(p->program, "ReflectOffset");
1136 p->loc_RefractColor = qglGetUniformLocation(p->program, "RefractColor");
1137 p->loc_Saturation = qglGetUniformLocation(p->program, "Saturation");
1138 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1139 p->loc_ScreenScaleRefractReflect = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1140 p->loc_ScreenToDepth = qglGetUniformLocation(p->program, "ScreenToDepth");
1141 p->loc_ShadowMap_Parameters = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1142 p->loc_ShadowMap_TextureScale = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1143 p->loc_SpecularPower = qglGetUniformLocation(p->program, "SpecularPower");
1144 p->loc_UserVec1 = qglGetUniformLocation(p->program, "UserVec1");
1145 p->loc_UserVec2 = qglGetUniformLocation(p->program, "UserVec2");
1146 p->loc_UserVec3 = qglGetUniformLocation(p->program, "UserVec3");
1147 p->loc_UserVec4 = qglGetUniformLocation(p->program, "UserVec4");
1148 p->loc_ViewTintColor = qglGetUniformLocation(p->program, "ViewTintColor");
1149 p->loc_ViewToLight = qglGetUniformLocation(p->program, "ViewToLight");
1150 p->loc_ModelToLight = qglGetUniformLocation(p->program, "ModelToLight");
1151 p->loc_TexMatrix = qglGetUniformLocation(p->program, "TexMatrix");
1152 p->loc_BackgroundTexMatrix = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1153 p->loc_ModelViewMatrix = qglGetUniformLocation(p->program, "ModelViewMatrix");
1154 p->loc_ModelViewProjectionMatrix = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1155 p->loc_PixelToScreenTexCoord = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1156 p->loc_ModelToReflectCube = qglGetUniformLocation(p->program, "ModelToReflectCube");
1157 p->loc_ShadowMapMatrix = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1158 p->loc_BloomColorSubtract = qglGetUniformLocation(p->program, "BloomColorSubtract");
1159 p->loc_NormalmapScrollBlend = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1160 p->loc_BounceGridMatrix = qglGetUniformLocation(p->program, "BounceGridMatrix");
1161 p->loc_BounceGridIntensity = qglGetUniformLocation(p->program, "BounceGridIntensity");
1162 // initialize the samplers to refer to the texture units we use
1163 p->tex_Texture_First = -1;
1164 p->tex_Texture_Second = -1;
1165 p->tex_Texture_GammaRamps = -1;
1166 p->tex_Texture_Normal = -1;
1167 p->tex_Texture_Color = -1;
1168 p->tex_Texture_Gloss = -1;
1169 p->tex_Texture_Glow = -1;
1170 p->tex_Texture_SecondaryNormal = -1;
1171 p->tex_Texture_SecondaryColor = -1;
1172 p->tex_Texture_SecondaryGloss = -1;
1173 p->tex_Texture_SecondaryGlow = -1;
1174 p->tex_Texture_Pants = -1;
1175 p->tex_Texture_Shirt = -1;
1176 p->tex_Texture_FogHeightTexture = -1;
1177 p->tex_Texture_FogMask = -1;
1178 p->tex_Texture_Lightmap = -1;
1179 p->tex_Texture_Deluxemap = -1;
1180 p->tex_Texture_Attenuation = -1;
1181 p->tex_Texture_Cube = -1;
1182 p->tex_Texture_Refraction = -1;
1183 p->tex_Texture_Reflection = -1;
1184 p->tex_Texture_ShadowMap2D = -1;
1185 p->tex_Texture_CubeProjection = -1;
1186 p->tex_Texture_ScreenDepth = -1;
1187 p->tex_Texture_ScreenNormalMap = -1;
1188 p->tex_Texture_ScreenDiffuse = -1;
1189 p->tex_Texture_ScreenSpecular = -1;
1190 p->tex_Texture_ReflectMask = -1;
1191 p->tex_Texture_ReflectCube = -1;
1192 p->tex_Texture_BounceGrid = -1;
1194 if (p->loc_Texture_First >= 0) {p->tex_Texture_First = sampler;qglUniform1i(p->loc_Texture_First , sampler);sampler++;}
1195 if (p->loc_Texture_Second >= 0) {p->tex_Texture_Second = sampler;qglUniform1i(p->loc_Texture_Second , sampler);sampler++;}
1196 if (p->loc_Texture_GammaRamps >= 0) {p->tex_Texture_GammaRamps = sampler;qglUniform1i(p->loc_Texture_GammaRamps , sampler);sampler++;}
1197 if (p->loc_Texture_Normal >= 0) {p->tex_Texture_Normal = sampler;qglUniform1i(p->loc_Texture_Normal , sampler);sampler++;}
1198 if (p->loc_Texture_Color >= 0) {p->tex_Texture_Color = sampler;qglUniform1i(p->loc_Texture_Color , sampler);sampler++;}
1199 if (p->loc_Texture_Gloss >= 0) {p->tex_Texture_Gloss = sampler;qglUniform1i(p->loc_Texture_Gloss , sampler);sampler++;}
1200 if (p->loc_Texture_Glow >= 0) {p->tex_Texture_Glow = sampler;qglUniform1i(p->loc_Texture_Glow , sampler);sampler++;}
1201 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1202 if (p->loc_Texture_SecondaryColor >= 0) {p->tex_Texture_SecondaryColor = sampler;qglUniform1i(p->loc_Texture_SecondaryColor , sampler);sampler++;}
1203 if (p->loc_Texture_SecondaryGloss >= 0) {p->tex_Texture_SecondaryGloss = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss , sampler);sampler++;}
1204 if (p->loc_Texture_SecondaryGlow >= 0) {p->tex_Texture_SecondaryGlow = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow , sampler);sampler++;}
1205 if (p->loc_Texture_Pants >= 0) {p->tex_Texture_Pants = sampler;qglUniform1i(p->loc_Texture_Pants , sampler);sampler++;}
1206 if (p->loc_Texture_Shirt >= 0) {p->tex_Texture_Shirt = sampler;qglUniform1i(p->loc_Texture_Shirt , sampler);sampler++;}
1207 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1208 if (p->loc_Texture_FogMask >= 0) {p->tex_Texture_FogMask = sampler;qglUniform1i(p->loc_Texture_FogMask , sampler);sampler++;}
1209 if (p->loc_Texture_Lightmap >= 0) {p->tex_Texture_Lightmap = sampler;qglUniform1i(p->loc_Texture_Lightmap , sampler);sampler++;}
1210 if (p->loc_Texture_Deluxemap >= 0) {p->tex_Texture_Deluxemap = sampler;qglUniform1i(p->loc_Texture_Deluxemap , sampler);sampler++;}
1211 if (p->loc_Texture_Attenuation >= 0) {p->tex_Texture_Attenuation = sampler;qglUniform1i(p->loc_Texture_Attenuation , sampler);sampler++;}
1212 if (p->loc_Texture_Cube >= 0) {p->tex_Texture_Cube = sampler;qglUniform1i(p->loc_Texture_Cube , sampler);sampler++;}
1213 if (p->loc_Texture_Refraction >= 0) {p->tex_Texture_Refraction = sampler;qglUniform1i(p->loc_Texture_Refraction , sampler);sampler++;}
1214 if (p->loc_Texture_Reflection >= 0) {p->tex_Texture_Reflection = sampler;qglUniform1i(p->loc_Texture_Reflection , sampler);sampler++;}
1215 if (p->loc_Texture_ShadowMap2D >= 0) {p->tex_Texture_ShadowMap2D = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D , sampler);sampler++;}
1216 if (p->loc_Texture_CubeProjection >= 0) {p->tex_Texture_CubeProjection = sampler;qglUniform1i(p->loc_Texture_CubeProjection , sampler);sampler++;}
1217 if (p->loc_Texture_ScreenDepth >= 0) {p->tex_Texture_ScreenDepth = sampler;qglUniform1i(p->loc_Texture_ScreenDepth , sampler);sampler++;}
1218 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1219 if (p->loc_Texture_ScreenDiffuse >= 0) {p->tex_Texture_ScreenDiffuse = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse , sampler);sampler++;}
1220 if (p->loc_Texture_ScreenSpecular >= 0) {p->tex_Texture_ScreenSpecular = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular , sampler);sampler++;}
1221 if (p->loc_Texture_ReflectMask >= 0) {p->tex_Texture_ReflectMask = sampler;qglUniform1i(p->loc_Texture_ReflectMask , sampler);sampler++;}
1222 if (p->loc_Texture_ReflectCube >= 0) {p->tex_Texture_ReflectCube = sampler;qglUniform1i(p->loc_Texture_ReflectCube , sampler);sampler++;}
1223 if (p->loc_Texture_BounceGrid >= 0) {p->tex_Texture_BounceGrid = sampler;qglUniform1i(p->loc_Texture_BounceGrid , sampler);sampler++;}
1225 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1228 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
1232 Mem_Free(vertexstring);
1234 Mem_Free(geometrystring);
1236 Mem_Free(fragmentstring);
1239 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1241 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1242 if (r_glsl_permutation != perm)
1244 r_glsl_permutation = perm;
1245 if (!r_glsl_permutation->program)
1247 if (!r_glsl_permutation->compiled)
1248 R_GLSL_CompilePermutation(perm, mode, permutation);
1249 if (!r_glsl_permutation->program)
1251 // remove features until we find a valid permutation
1253 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1255 // reduce i more quickly whenever it would not remove any bits
1256 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1257 if (!(permutation & j))
1260 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1261 if (!r_glsl_permutation->compiled)
1262 R_GLSL_CompilePermutation(perm, mode, permutation);
1263 if (r_glsl_permutation->program)
1266 if (i >= SHADERPERMUTATION_COUNT)
1268 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1269 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1270 qglUseProgram(0);CHECKGLERROR
1271 return; // no bit left to clear, entire mode is broken
1276 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1278 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1279 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1280 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1287 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1288 extern D3DCAPS9 vid_d3d9caps;
1291 struct r_hlsl_permutation_s;
1292 typedef struct r_hlsl_permutation_s
1294 /// hash lookup data
1295 struct r_hlsl_permutation_s *hashnext;
1297 unsigned int permutation;
1299 /// indicates if we have tried compiling this permutation already
1301 /// NULL if compilation failed
1302 IDirect3DVertexShader9 *vertexshader;
1303 IDirect3DPixelShader9 *pixelshader;
1305 r_hlsl_permutation_t;
1307 typedef enum D3DVSREGISTER_e
1309 D3DVSREGISTER_TexMatrix = 0, // float4x4
1310 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1311 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1312 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1313 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1314 D3DVSREGISTER_ModelToLight = 20, // float4x4
1315 D3DVSREGISTER_EyePosition = 24,
1316 D3DVSREGISTER_FogPlane = 25,
1317 D3DVSREGISTER_LightDir = 26,
1318 D3DVSREGISTER_LightPosition = 27,
1322 typedef enum D3DPSREGISTER_e
1324 D3DPSREGISTER_Alpha = 0,
1325 D3DPSREGISTER_BloomBlur_Parameters = 1,
1326 D3DPSREGISTER_ClientTime = 2,
1327 D3DPSREGISTER_Color_Ambient = 3,
1328 D3DPSREGISTER_Color_Diffuse = 4,
1329 D3DPSREGISTER_Color_Specular = 5,
1330 D3DPSREGISTER_Color_Glow = 6,
1331 D3DPSREGISTER_Color_Pants = 7,
1332 D3DPSREGISTER_Color_Shirt = 8,
1333 D3DPSREGISTER_DeferredColor_Ambient = 9,
1334 D3DPSREGISTER_DeferredColor_Diffuse = 10,
1335 D3DPSREGISTER_DeferredColor_Specular = 11,
1336 D3DPSREGISTER_DeferredMod_Diffuse = 12,
1337 D3DPSREGISTER_DeferredMod_Specular = 13,
1338 D3DPSREGISTER_DistortScaleRefractReflect = 14,
1339 D3DPSREGISTER_EyePosition = 15, // unused
1340 D3DPSREGISTER_FogColor = 16,
1341 D3DPSREGISTER_FogHeightFade = 17,
1342 D3DPSREGISTER_FogPlane = 18,
1343 D3DPSREGISTER_FogPlaneViewDist = 19,
1344 D3DPSREGISTER_FogRangeRecip = 20,
1345 D3DPSREGISTER_LightColor = 21,
1346 D3DPSREGISTER_LightDir = 22, // unused
1347 D3DPSREGISTER_LightPosition = 23,
1348 D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1349 D3DPSREGISTER_PixelSize = 25,
1350 D3DPSREGISTER_ReflectColor = 26,
1351 D3DPSREGISTER_ReflectFactor = 27,
1352 D3DPSREGISTER_ReflectOffset = 28,
1353 D3DPSREGISTER_RefractColor = 29,
1354 D3DPSREGISTER_Saturation = 30,
1355 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1356 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1357 D3DPSREGISTER_ScreenToDepth = 33,
1358 D3DPSREGISTER_ShadowMap_Parameters = 34,
1359 D3DPSREGISTER_ShadowMap_TextureScale = 35,
1360 D3DPSREGISTER_SpecularPower = 36,
1361 D3DPSREGISTER_UserVec1 = 37,
1362 D3DPSREGISTER_UserVec2 = 38,
1363 D3DPSREGISTER_UserVec3 = 39,
1364 D3DPSREGISTER_UserVec4 = 40,
1365 D3DPSREGISTER_ViewTintColor = 41,
1366 D3DPSREGISTER_PixelToScreenTexCoord = 42,
1367 D3DPSREGISTER_BloomColorSubtract = 43,
1368 D3DPSREGISTER_ViewToLight = 44, // float4x4
1369 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1370 D3DPSREGISTER_NormalmapScrollBlend = 52,
1375 /// information about each possible shader permutation
1376 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1377 /// currently selected permutation
1378 r_hlsl_permutation_t *r_hlsl_permutation;
1379 /// storage for permutations linked in the hash table
1380 memexpandablearray_t r_hlsl_permutationarray;
1382 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1384 //unsigned int hashdepth = 0;
1385 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1386 r_hlsl_permutation_t *p;
1387 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1389 if (p->mode == mode && p->permutation == permutation)
1391 //if (hashdepth > 10)
1392 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1397 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1399 p->permutation = permutation;
1400 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1401 r_hlsl_permutationhash[mode][hashindex] = p;
1402 //if (hashdepth > 10)
1403 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1407 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1410 if (!filename || !filename[0])
1412 if (!strcmp(filename, "hlsl/default.hlsl"))
1414 if (!hlslshaderstring)
1416 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1417 if (hlslshaderstring)
1418 Con_DPrintf("Loading shaders from file %s...\n", filename);
1420 hlslshaderstring = (char *)builtinhlslshaderstring;
1422 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1423 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1424 return shaderstring;
1426 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1429 if (printfromdisknotice)
1430 Con_DPrintf("from disk %s... ", filename);
1431 return shaderstring;
1433 return shaderstring;
1437 //#include <d3dx9shader.h>
1438 //#include <d3dx9mesh.h>
1440 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1442 DWORD *vsbin = NULL;
1443 DWORD *psbin = NULL;
1444 fs_offset_t vsbinsize;
1445 fs_offset_t psbinsize;
1446 // IDirect3DVertexShader9 *vs = NULL;
1447 // IDirect3DPixelShader9 *ps = NULL;
1448 ID3DXBuffer *vslog = NULL;
1449 ID3DXBuffer *vsbuffer = NULL;
1450 ID3DXConstantTable *vsconstanttable = NULL;
1451 ID3DXBuffer *pslog = NULL;
1452 ID3DXBuffer *psbuffer = NULL;
1453 ID3DXConstantTable *psconstanttable = NULL;
1456 char temp[MAX_INPUTLINE];
1457 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1458 qboolean debugshader = gl_paranoid.integer != 0;
1459 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1460 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1463 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1464 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1466 if ((!vsbin && vertstring) || (!psbin && fragstring))
1468 const char* dllnames_d3dx9 [] =
1492 dllhandle_t d3dx9_dll = NULL;
1493 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1494 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1495 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1496 dllfunction_t d3dx9_dllfuncs[] =
1498 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
1499 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
1500 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
1503 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1505 DWORD shaderflags = 0;
1507 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1508 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1509 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1510 if (vertstring && vertstring[0])
1514 // vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1515 // FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1516 FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1517 vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1520 vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1523 vsbinsize = vsbuffer->GetBufferSize();
1524 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1525 memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1526 vsbuffer->Release();
1530 strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1531 Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1535 if (fragstring && fragstring[0])
1539 // psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1540 // FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1541 FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1542 psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1545 psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1548 psbinsize = psbuffer->GetBufferSize();
1549 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1550 memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1551 psbuffer->Release();
1555 strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1556 Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1560 Sys_UnloadLibrary(&d3dx9_dll);
1563 Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1567 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1568 if (FAILED(vsresult))
1569 Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1570 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1571 if (FAILED(psresult))
1572 Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1574 // free the shader data
1575 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1576 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1579 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1582 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1583 int vertstring_length = 0;
1584 int geomstring_length = 0;
1585 int fragstring_length = 0;
1587 char *vertexstring, *geometrystring, *fragmentstring;
1588 char *vertstring, *geomstring, *fragstring;
1589 char permutationname[256];
1590 char cachename[256];
1591 int vertstrings_count = 0;
1592 int geomstrings_count = 0;
1593 int fragstrings_count = 0;
1594 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1595 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1596 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1601 p->vertexshader = NULL;
1602 p->pixelshader = NULL;
1604 permutationname[0] = 0;
1606 vertexstring = R_HLSL_GetText(modeinfo->vertexfilename, true);
1607 geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1608 fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1610 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1611 strlcat(cachename, "hlsl/", sizeof(cachename));
1613 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1614 vertstrings_count = 0;
1615 geomstrings_count = 0;
1616 fragstrings_count = 0;
1617 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1618 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1619 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1621 // the first pretext is which type of shader to compile as
1622 // (later these will all be bound together as a program object)
1623 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1624 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1625 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1627 // the second pretext is the mode (for example a light source)
1628 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1629 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1630 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1631 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1632 strlcat(cachename, modeinfo->name, sizeof(cachename));
1634 // now add all the permutation pretexts
1635 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1637 if (permutation & (1<<i))
1639 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1640 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1641 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1642 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1643 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1647 // keep line numbers correct
1648 vertstrings_list[vertstrings_count++] = "\n";
1649 geomstrings_list[geomstrings_count++] = "\n";
1650 fragstrings_list[fragstrings_count++] = "\n";
1655 R_CompileShader_AddStaticParms(mode, permutation);
1656 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1657 vertstrings_count += shaderstaticparms_count;
1658 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1659 geomstrings_count += shaderstaticparms_count;
1660 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1661 fragstrings_count += shaderstaticparms_count;
1663 // replace spaces in the cachename with _ characters
1664 for (i = 0;cachename[i];i++)
1665 if (cachename[i] == ' ')
1668 // now append the shader text itself
1669 vertstrings_list[vertstrings_count++] = vertexstring;
1670 geomstrings_list[geomstrings_count++] = geometrystring;
1671 fragstrings_list[fragstrings_count++] = fragmentstring;
1673 // if any sources were NULL, clear the respective list
1675 vertstrings_count = 0;
1676 if (!geometrystring)
1677 geomstrings_count = 0;
1678 if (!fragmentstring)
1679 fragstrings_count = 0;
1681 vertstring_length = 0;
1682 for (i = 0;i < vertstrings_count;i++)
1683 vertstring_length += strlen(vertstrings_list[i]);
1684 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1685 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1686 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1688 geomstring_length = 0;
1689 for (i = 0;i < geomstrings_count;i++)
1690 geomstring_length += strlen(geomstrings_list[i]);
1691 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1692 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1693 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1695 fragstring_length = 0;
1696 for (i = 0;i < fragstrings_count;i++)
1697 fragstring_length += strlen(fragstrings_list[i]);
1698 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1699 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1700 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1702 // try to load the cached shader, or generate one
1703 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1705 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1706 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1708 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
1712 Mem_Free(vertstring);
1714 Mem_Free(geomstring);
1716 Mem_Free(fragstring);
1718 Mem_Free(vertexstring);
1720 Mem_Free(geometrystring);
1722 Mem_Free(fragmentstring);
1725 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1726 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1727 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);}
1728 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);}
1729 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);}
1730 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);}
1732 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1733 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1734 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);}
1735 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);}
1736 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);}
1737 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);}
1739 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1741 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1742 if (r_hlsl_permutation != perm)
1744 r_hlsl_permutation = perm;
1745 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1747 if (!r_hlsl_permutation->compiled)
1748 R_HLSL_CompilePermutation(perm, mode, permutation);
1749 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1751 // remove features until we find a valid permutation
1753 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1755 // reduce i more quickly whenever it would not remove any bits
1756 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1757 if (!(permutation & j))
1760 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1761 if (!r_hlsl_permutation->compiled)
1762 R_HLSL_CompilePermutation(perm, mode, permutation);
1763 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1766 if (i >= SHADERPERMUTATION_COUNT)
1768 //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1769 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1770 return; // no bit left to clear, entire mode is broken
1774 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1775 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1777 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1778 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1779 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1783 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1785 DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1786 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1787 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1788 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1791 void R_GLSL_Restart_f(void)
1793 unsigned int i, limit;
1794 if (glslshaderstring && glslshaderstring != builtinshaderstring)
1795 Mem_Free(glslshaderstring);
1796 glslshaderstring = NULL;
1797 if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1798 Mem_Free(hlslshaderstring);
1799 hlslshaderstring = NULL;
1800 switch(vid.renderpath)
1802 case RENDERPATH_D3D9:
1805 r_hlsl_permutation_t *p;
1806 r_hlsl_permutation = NULL;
1807 limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1808 for (i = 0;i < limit;i++)
1810 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1812 if (p->vertexshader)
1813 IDirect3DVertexShader9_Release(p->vertexshader);
1815 IDirect3DPixelShader9_Release(p->pixelshader);
1816 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1819 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1823 case RENDERPATH_D3D10:
1824 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1826 case RENDERPATH_D3D11:
1827 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1829 case RENDERPATH_GL20:
1830 case RENDERPATH_GLES2:
1832 r_glsl_permutation_t *p;
1833 r_glsl_permutation = NULL;
1834 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1835 for (i = 0;i < limit;i++)
1837 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1839 GL_Backend_FreeProgram(p->program);
1840 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1843 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1846 case RENDERPATH_GL11:
1847 case RENDERPATH_GL13:
1848 case RENDERPATH_GLES1:
1850 case RENDERPATH_SOFT:
1855 void R_GLSL_DumpShader_f(void)
1860 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1863 FS_Print(file, "/* The engine may define the following macros:\n");
1864 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1865 for (i = 0;i < SHADERMODE_COUNT;i++)
1866 FS_Print(file, glslshadermodeinfo[i].pretext);
1867 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1868 FS_Print(file, shaderpermutationinfo[i].pretext);
1869 FS_Print(file, "*/\n");
1870 FS_Print(file, builtinshaderstring);
1872 Con_Printf("glsl/default.glsl written\n");
1875 Con_Printf("failed to write to glsl/default.glsl\n");
1877 file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1880 FS_Print(file, "/* The engine may define the following macros:\n");
1881 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1882 for (i = 0;i < SHADERMODE_COUNT;i++)
1883 FS_Print(file, hlslshadermodeinfo[i].pretext);
1884 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1885 FS_Print(file, shaderpermutationinfo[i].pretext);
1886 FS_Print(file, "*/\n");
1887 FS_Print(file, builtinhlslshaderstring);
1889 Con_Printf("hlsl/default.hlsl written\n");
1892 Con_Printf("failed to write to hlsl/default.hlsl\n");
1895 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
1898 texturemode = GL_MODULATE;
1899 switch (vid.renderpath)
1901 case RENDERPATH_D3D9:
1903 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1904 R_Mesh_TexBind(GL20TU_FIRST , first );
1905 R_Mesh_TexBind(GL20TU_SECOND, second);
1908 case RENDERPATH_D3D10:
1909 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1911 case RENDERPATH_D3D11:
1912 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1914 case RENDERPATH_GL20:
1915 case RENDERPATH_GLES2:
1916 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1917 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1918 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1920 case RENDERPATH_GL13:
1921 case RENDERPATH_GLES1:
1922 R_Mesh_TexBind(0, first );
1923 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1924 R_Mesh_TexBind(1, second);
1926 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1928 case RENDERPATH_GL11:
1929 R_Mesh_TexBind(0, first );
1931 case RENDERPATH_SOFT:
1932 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1933 R_Mesh_TexBind(GL20TU_FIRST , first );
1934 R_Mesh_TexBind(GL20TU_SECOND, second);
1939 void R_SetupShader_DepthOrShadow(void)
1941 switch (vid.renderpath)
1943 case RENDERPATH_D3D9:
1945 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1948 case RENDERPATH_D3D10:
1949 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1951 case RENDERPATH_D3D11:
1952 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1954 case RENDERPATH_GL20:
1955 case RENDERPATH_GLES2:
1956 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1958 case RENDERPATH_GL13:
1959 case RENDERPATH_GLES1:
1960 R_Mesh_TexBind(0, 0);
1961 R_Mesh_TexBind(1, 0);
1963 case RENDERPATH_GL11:
1964 R_Mesh_TexBind(0, 0);
1966 case RENDERPATH_SOFT:
1967 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
1972 void R_SetupShader_ShowDepth(void)
1974 switch (vid.renderpath)
1976 case RENDERPATH_D3D9:
1978 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
1981 case RENDERPATH_D3D10:
1982 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1984 case RENDERPATH_D3D11:
1985 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1987 case RENDERPATH_GL20:
1988 case RENDERPATH_GLES2:
1989 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
1991 case RENDERPATH_GL13:
1992 case RENDERPATH_GLES1:
1994 case RENDERPATH_GL11:
1996 case RENDERPATH_SOFT:
1997 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
2002 extern qboolean r_shadow_usingdeferredprepass;
2003 extern cvar_t r_shadow_deferred_8bitrange;
2004 extern rtexture_t *r_shadow_attenuationgradienttexture;
2005 extern rtexture_t *r_shadow_attenuation2dtexture;
2006 extern rtexture_t *r_shadow_attenuation3dtexture;
2007 extern qboolean r_shadow_usingshadowmap2d;
2008 extern qboolean r_shadow_usingshadowmaportho;
2009 extern float r_shadow_shadowmap_texturescale[2];
2010 extern float r_shadow_shadowmap_parameters[4];
2011 extern qboolean r_shadow_shadowmapvsdct;
2012 extern qboolean r_shadow_shadowmapsampler;
2013 extern int r_shadow_shadowmappcf;
2014 extern rtexture_t *r_shadow_shadowmap2dtexture;
2015 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2016 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2017 extern matrix4x4_t r_shadow_shadowmapmatrix;
2018 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2019 extern int r_shadow_prepass_width;
2020 extern int r_shadow_prepass_height;
2021 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2022 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2023 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2024 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2025 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2027 #define BLENDFUNC_ALLOWS_COLORMOD 1
2028 #define BLENDFUNC_ALLOWS_FOG 2
2029 #define BLENDFUNC_ALLOWS_FOG_HACK0 4
2030 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2031 #define BLENDFUNC_ALLOWS_ANYFOG (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2032 static int R_BlendFuncFlags(int src, int dst)
2036 // a blendfunc allows colormod if:
2037 // a) it can never keep the destination pixel invariant, or
2038 // b) it can keep the destination pixel invariant, and still can do so if colormodded
2039 // this is to prevent unintended side effects from colormod
2041 // a blendfunc allows fog if:
2042 // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2043 // this is to prevent unintended side effects from fog
2045 // these checks are the output of fogeval.pl
2047 r |= BLENDFUNC_ALLOWS_COLORMOD;
2048 if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2049 if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2050 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2051 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2052 if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2053 if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2054 if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2055 if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2056 if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2057 if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2058 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2059 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2060 if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2061 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2062 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2063 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2064 if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2065 if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2066 if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2067 if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2068 if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2073 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)
2075 // select a permutation of the lighting shader appropriate to this
2076 // combination of texture, entity, light source, and fogging, only use the
2077 // minimum features necessary to avoid wasting rendering time in the
2078 // fragment shader on features that are not being used
2079 unsigned int permutation = 0;
2080 unsigned int mode = 0;
2082 static float dummy_colormod[3] = {1, 1, 1};
2083 float *colormod = rsurface.colormod;
2085 matrix4x4_t tempmatrix;
2086 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2087 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2088 permutation |= SHADERPERMUTATION_ALPHAKILL;
2089 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2090 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2091 if (rsurfacepass == RSURFPASS_BACKGROUND)
2093 // distorted background
2094 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2096 mode = SHADERMODE_WATER;
2097 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2099 // this is the right thing to do for wateralpha
2100 GL_BlendFunc(GL_ONE, GL_ZERO);
2101 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2105 // this is the right thing to do for entity alpha
2106 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2107 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2110 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2112 mode = SHADERMODE_REFRACTION;
2113 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2114 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2118 mode = SHADERMODE_GENERIC;
2119 permutation |= SHADERPERMUTATION_DIFFUSE;
2120 GL_BlendFunc(GL_ONE, GL_ZERO);
2121 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2124 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2126 if (r_glsl_offsetmapping.integer)
2128 switch(rsurface.texture->offsetmapping)
2130 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2131 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2132 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2133 case OFFSETMAPPING_OFF: break;
2136 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2137 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2138 // normalmap (deferred prepass), may use alpha test on diffuse
2139 mode = SHADERMODE_DEFERREDGEOMETRY;
2140 GL_BlendFunc(GL_ONE, GL_ZERO);
2141 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2143 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2145 if (r_glsl_offsetmapping.integer)
2147 switch(rsurface.texture->offsetmapping)
2149 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2150 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2151 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2152 case OFFSETMAPPING_OFF: break;
2155 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2156 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2158 mode = SHADERMODE_LIGHTSOURCE;
2159 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2160 permutation |= SHADERPERMUTATION_CUBEFILTER;
2161 if (diffusescale > 0)
2162 permutation |= SHADERPERMUTATION_DIFFUSE;
2163 if (specularscale > 0)
2164 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2165 if (r_refdef.fogenabled)
2166 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2167 if (rsurface.texture->colormapping)
2168 permutation |= SHADERPERMUTATION_COLORMAPPING;
2169 if (r_shadow_usingshadowmap2d)
2171 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2172 if(r_shadow_shadowmapvsdct)
2173 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2175 if (r_shadow_shadowmapsampler)
2176 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2177 if (r_shadow_shadowmappcf > 1)
2178 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2179 else if (r_shadow_shadowmappcf)
2180 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2182 if (rsurface.texture->reflectmasktexture)
2183 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2184 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2185 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2187 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2189 if (r_glsl_offsetmapping.integer)
2191 switch(rsurface.texture->offsetmapping)
2193 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2194 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2195 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2196 case OFFSETMAPPING_OFF: break;
2199 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2200 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2201 // unshaded geometry (fullbright or ambient model lighting)
2202 mode = SHADERMODE_FLATCOLOR;
2203 ambientscale = diffusescale = specularscale = 0;
2204 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2205 permutation |= SHADERPERMUTATION_GLOW;
2206 if (r_refdef.fogenabled)
2207 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2208 if (rsurface.texture->colormapping)
2209 permutation |= SHADERPERMUTATION_COLORMAPPING;
2210 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2212 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2213 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2215 if (r_shadow_shadowmapsampler)
2216 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2217 if (r_shadow_shadowmappcf > 1)
2218 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2219 else if (r_shadow_shadowmappcf)
2220 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2222 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2223 permutation |= SHADERPERMUTATION_REFLECTION;
2224 if (rsurface.texture->reflectmasktexture)
2225 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2226 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2227 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2229 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2231 if (r_glsl_offsetmapping.integer)
2233 switch(rsurface.texture->offsetmapping)
2235 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2236 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2237 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2238 case OFFSETMAPPING_OFF: break;
2241 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2242 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2243 // directional model lighting
2244 mode = SHADERMODE_LIGHTDIRECTION;
2245 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2246 permutation |= SHADERPERMUTATION_GLOW;
2247 permutation |= SHADERPERMUTATION_DIFFUSE;
2248 if (specularscale > 0)
2249 permutation |= SHADERPERMUTATION_SPECULAR;
2250 if (r_refdef.fogenabled)
2251 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2252 if (rsurface.texture->colormapping)
2253 permutation |= SHADERPERMUTATION_COLORMAPPING;
2254 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2256 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2257 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2259 if (r_shadow_shadowmapsampler)
2260 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2261 if (r_shadow_shadowmappcf > 1)
2262 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2263 else if (r_shadow_shadowmappcf)
2264 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2266 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2267 permutation |= SHADERPERMUTATION_REFLECTION;
2268 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2269 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2270 if (rsurface.texture->reflectmasktexture)
2271 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2272 if (r_shadow_bouncegridtexture)
2274 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2275 if (r_shadow_bouncegriddirectional)
2276 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2278 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2279 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2281 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2283 if (r_glsl_offsetmapping.integer)
2285 switch(rsurface.texture->offsetmapping)
2287 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2288 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2289 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2290 case OFFSETMAPPING_OFF: break;
2293 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2294 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2295 // ambient model lighting
2296 mode = SHADERMODE_LIGHTDIRECTION;
2297 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2298 permutation |= SHADERPERMUTATION_GLOW;
2299 if (r_refdef.fogenabled)
2300 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2301 if (rsurface.texture->colormapping)
2302 permutation |= SHADERPERMUTATION_COLORMAPPING;
2303 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2305 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2306 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2308 if (r_shadow_shadowmapsampler)
2309 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2310 if (r_shadow_shadowmappcf > 1)
2311 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2312 else if (r_shadow_shadowmappcf)
2313 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2315 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2316 permutation |= SHADERPERMUTATION_REFLECTION;
2317 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2318 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2319 if (rsurface.texture->reflectmasktexture)
2320 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2321 if (r_shadow_bouncegridtexture)
2323 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2324 if (r_shadow_bouncegriddirectional)
2325 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2327 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2328 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2332 if (r_glsl_offsetmapping.integer)
2334 switch(rsurface.texture->offsetmapping)
2336 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2337 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2338 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2339 case OFFSETMAPPING_OFF: break;
2342 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2343 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2345 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2346 permutation |= SHADERPERMUTATION_GLOW;
2347 if (r_refdef.fogenabled)
2348 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2349 if (rsurface.texture->colormapping)
2350 permutation |= SHADERPERMUTATION_COLORMAPPING;
2351 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2353 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2354 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2356 if (r_shadow_shadowmapsampler)
2357 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2358 if (r_shadow_shadowmappcf > 1)
2359 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2360 else if (r_shadow_shadowmappcf)
2361 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2363 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2364 permutation |= SHADERPERMUTATION_REFLECTION;
2365 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2366 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2367 if (rsurface.texture->reflectmasktexture)
2368 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2369 if (FAKELIGHT_ENABLED)
2371 // fake lightmapping (q1bsp, q3bsp, fullbright map)
2372 mode = SHADERMODE_FAKELIGHT;
2373 permutation |= SHADERPERMUTATION_DIFFUSE;
2374 if (specularscale > 0)
2375 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2377 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2379 // deluxemapping (light direction texture)
2380 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2381 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2383 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2384 permutation |= SHADERPERMUTATION_DIFFUSE;
2385 if (specularscale > 0)
2386 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2388 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2390 // fake deluxemapping (uniform light direction in tangentspace)
2391 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2392 permutation |= SHADERPERMUTATION_DIFFUSE;
2393 if (specularscale > 0)
2394 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2396 else if (rsurface.uselightmaptexture)
2398 // ordinary lightmapping (q1bsp, q3bsp)
2399 mode = SHADERMODE_LIGHTMAP;
2403 // ordinary vertex coloring (q3bsp)
2404 mode = SHADERMODE_VERTEXCOLOR;
2406 if (r_shadow_bouncegridtexture)
2408 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2409 if (r_shadow_bouncegriddirectional)
2410 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2412 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2413 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2415 if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2416 colormod = dummy_colormod;
2417 if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2418 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2419 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2420 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2421 switch(vid.renderpath)
2423 case RENDERPATH_D3D9:
2425 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);
2426 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2427 R_SetupShader_SetPermutationHLSL(mode, permutation);
2428 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2429 if (mode == SHADERMODE_LIGHTSOURCE)
2431 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2432 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2436 if (mode == SHADERMODE_LIGHTDIRECTION)
2438 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2441 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2442 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2443 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2444 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2445 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2447 if (mode == SHADERMODE_LIGHTSOURCE)
2449 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2450 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2451 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2452 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2453 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2455 // additive passes are only darkened by fog, not tinted
2456 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2457 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2461 if (mode == SHADERMODE_FLATCOLOR)
2463 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2465 else if (mode == SHADERMODE_LIGHTDIRECTION)
2467 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]);
2468 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2469 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);
2470 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);
2471 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2472 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2473 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2477 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2478 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2479 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);
2480 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);
2481 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2483 // additive passes are only darkened by fog, not tinted
2484 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2485 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2487 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2488 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);
2489 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2490 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2491 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2492 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2493 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2494 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2495 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2496 if (mode == SHADERMODE_WATER)
2497 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2499 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2500 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2501 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2502 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));
2503 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2504 if (rsurface.texture->pantstexture)
2505 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2507 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2508 if (rsurface.texture->shirttexture)
2509 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2511 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2512 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2513 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2514 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2515 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2516 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2517 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2518 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2519 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2520 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2522 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2523 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2525 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2526 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2527 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2528 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2529 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2530 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2531 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2532 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2533 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2534 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2535 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2536 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2537 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2538 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2539 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2540 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2541 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2542 if (rsurfacepass == RSURFPASS_BACKGROUND)
2544 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2545 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2546 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2550 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2552 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2553 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2554 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2555 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2556 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2558 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2559 if (rsurface.rtlight)
2561 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2562 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2567 case RENDERPATH_D3D10:
2568 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2570 case RENDERPATH_D3D11:
2571 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2573 case RENDERPATH_GL20:
2574 case RENDERPATH_GLES2:
2575 if (!vid.useinterleavedarrays)
2577 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);
2578 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2579 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2580 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2581 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2582 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2583 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2584 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2588 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);
2589 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2591 R_SetupShader_SetPermutationGLSL(mode, permutation);
2592 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2593 if (mode == SHADERMODE_LIGHTSOURCE)
2595 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2596 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2597 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2598 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2599 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2600 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);
2602 // additive passes are only darkened by fog, not tinted
2603 if (r_glsl_permutation->loc_FogColor >= 0)
2604 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2605 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2609 if (mode == SHADERMODE_FLATCOLOR)
2611 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2613 else if (mode == SHADERMODE_LIGHTDIRECTION)
2615 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]);
2616 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]);
2617 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);
2618 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);
2619 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);
2620 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]);
2621 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]);
2625 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]);
2626 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]);
2627 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);
2628 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);
2629 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);
2631 // additive passes are only darkened by fog, not tinted
2632 if (r_glsl_permutation->loc_FogColor >= 0)
2634 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2635 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2637 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2639 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);
2640 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]);
2641 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]);
2642 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]);
2643 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]);
2644 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2645 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2646 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2647 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]);
2649 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2650 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2651 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2652 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]);
2653 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]);
2655 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2656 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));
2657 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2658 if (r_glsl_permutation->loc_Color_Pants >= 0)
2660 if (rsurface.texture->pantstexture)
2661 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2663 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2665 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2667 if (rsurface.texture->shirttexture)
2668 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2670 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2672 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]);
2673 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2674 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2675 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2676 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2677 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2678 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2679 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2680 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2682 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]);
2683 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2684 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);}
2685 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2687 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
2688 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
2689 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
2690 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
2691 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
2692 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
2693 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
2694 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
2695 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
2696 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
2697 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
2698 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
2699 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
2700 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
2701 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);
2702 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
2703 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
2704 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2705 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2706 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2707 if (rsurfacepass == RSURFPASS_BACKGROUND)
2709 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);
2710 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);
2711 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);
2715 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);
2717 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2718 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2719 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
2720 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
2721 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2723 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture );
2724 if (rsurface.rtlight)
2726 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2727 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2730 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2733 case RENDERPATH_GL11:
2734 case RENDERPATH_GL13:
2735 case RENDERPATH_GLES1:
2737 case RENDERPATH_SOFT:
2738 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);
2739 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2740 R_SetupShader_SetPermutationSoft(mode, permutation);
2741 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2742 if (mode == SHADERMODE_LIGHTSOURCE)
2744 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2745 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2746 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2747 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2748 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2749 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2751 // additive passes are only darkened by fog, not tinted
2752 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2753 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2757 if (mode == SHADERMODE_FLATCOLOR)
2759 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2761 else if (mode == SHADERMODE_LIGHTDIRECTION)
2763 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]);
2764 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2765 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);
2766 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);
2767 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2768 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]);
2769 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2773 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2774 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2775 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);
2776 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);
2777 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2779 // additive passes are only darkened by fog, not tinted
2780 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2781 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2783 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2784 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);
2785 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2786 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2787 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]);
2788 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]);
2789 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2790 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2791 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2792 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2794 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2795 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2796 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2797 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2798 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]);
2800 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2801 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));
2802 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2803 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2805 if (rsurface.texture->pantstexture)
2806 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2808 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2810 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2812 if (rsurface.texture->shirttexture)
2813 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2815 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2817 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2818 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2819 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2820 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2821 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2822 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2823 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2824 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2825 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2827 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2828 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2830 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2831 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2832 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2833 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2834 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2835 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2836 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2837 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2838 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2839 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2840 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2841 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2842 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2843 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2844 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2845 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2846 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2847 if (rsurfacepass == RSURFPASS_BACKGROUND)
2849 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2850 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2851 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2855 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2857 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2858 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2859 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2860 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2861 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2863 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2864 if (rsurface.rtlight)
2866 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2867 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2874 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2876 // select a permutation of the lighting shader appropriate to this
2877 // combination of texture, entity, light source, and fogging, only use the
2878 // minimum features necessary to avoid wasting rendering time in the
2879 // fragment shader on features that are not being used
2880 unsigned int permutation = 0;
2881 unsigned int mode = 0;
2882 const float *lightcolorbase = rtlight->currentcolor;
2883 float ambientscale = rtlight->ambientscale;
2884 float diffusescale = rtlight->diffusescale;
2885 float specularscale = rtlight->specularscale;
2886 // this is the location of the light in view space
2887 vec3_t viewlightorigin;
2888 // this transforms from view space (camera) to light space (cubemap)
2889 matrix4x4_t viewtolight;
2890 matrix4x4_t lighttoview;
2891 float viewtolight16f[16];
2892 float range = 1.0f / r_shadow_deferred_8bitrange.value;
2894 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2895 if (rtlight->currentcubemap != r_texture_whitecube)
2896 permutation |= SHADERPERMUTATION_CUBEFILTER;
2897 if (diffusescale > 0)
2898 permutation |= SHADERPERMUTATION_DIFFUSE;
2899 if (specularscale > 0 && r_shadow_gloss.integer > 0)
2900 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2901 if (r_shadow_usingshadowmap2d)
2903 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2904 if (r_shadow_shadowmapvsdct)
2905 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2907 if (r_shadow_shadowmapsampler)
2908 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2909 if (r_shadow_shadowmappcf > 1)
2910 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2911 else if (r_shadow_shadowmappcf)
2912 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2914 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2915 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2916 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2917 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2918 switch(vid.renderpath)
2920 case RENDERPATH_D3D9:
2922 R_SetupShader_SetPermutationHLSL(mode, permutation);
2923 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2924 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
2925 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2926 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2927 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2928 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2929 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2930 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2931 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2932 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2934 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2935 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthcolortexture );
2936 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2937 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2938 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dcolortexture );
2939 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2942 case RENDERPATH_D3D10:
2943 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2945 case RENDERPATH_D3D11:
2946 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2948 case RENDERPATH_GL20:
2949 case RENDERPATH_GLES2:
2950 R_SetupShader_SetPermutationGLSL(mode, permutation);
2951 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2952 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
2953 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);
2954 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);
2955 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);
2956 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]);
2957 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]);
2958 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));
2959 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]);
2960 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
2962 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2963 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2964 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2965 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2966 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );
2967 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2969 case RENDERPATH_GL11:
2970 case RENDERPATH_GL13:
2971 case RENDERPATH_GLES1:
2973 case RENDERPATH_SOFT:
2974 R_SetupShader_SetPermutationGLSL(mode, permutation);
2975 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2976 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
2977 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2978 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2979 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2980 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2981 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]);
2982 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));
2983 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2984 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2986 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2987 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2988 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2989 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2990 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
2991 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2996 #define SKINFRAME_HASH 1024
3000 int loadsequence; // incremented each level change
3001 memexpandablearray_t array;
3002 skinframe_t *hash[SKINFRAME_HASH];
3005 r_skinframe_t r_skinframe;
3007 void R_SkinFrame_PrepareForPurge(void)
3009 r_skinframe.loadsequence++;
3010 // wrap it without hitting zero
3011 if (r_skinframe.loadsequence >= 200)
3012 r_skinframe.loadsequence = 1;
3015 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3019 // mark the skinframe as used for the purging code
3020 skinframe->loadsequence = r_skinframe.loadsequence;
3023 void R_SkinFrame_Purge(void)
3027 for (i = 0;i < SKINFRAME_HASH;i++)
3029 for (s = r_skinframe.hash[i];s;s = s->next)
3031 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3033 if (s->merged == s->base)
3035 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3036 R_PurgeTexture(s->stain );s->stain = NULL;
3037 R_PurgeTexture(s->merged);s->merged = NULL;
3038 R_PurgeTexture(s->base );s->base = NULL;
3039 R_PurgeTexture(s->pants );s->pants = NULL;
3040 R_PurgeTexture(s->shirt );s->shirt = NULL;
3041 R_PurgeTexture(s->nmap );s->nmap = NULL;
3042 R_PurgeTexture(s->gloss );s->gloss = NULL;
3043 R_PurgeTexture(s->glow );s->glow = NULL;
3044 R_PurgeTexture(s->fog );s->fog = NULL;
3045 R_PurgeTexture(s->reflect);s->reflect = NULL;
3046 s->loadsequence = 0;
3052 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3054 char basename[MAX_QPATH];
3056 Image_StripImageExtension(name, basename, sizeof(basename));
3058 if( last == NULL ) {
3060 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3061 item = r_skinframe.hash[hashindex];
3066 // linearly search through the hash bucket
3067 for( ; item ; item = item->next ) {
3068 if( !strcmp( item->basename, basename ) ) {
3075 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3079 char basename[MAX_QPATH];
3081 Image_StripImageExtension(name, basename, sizeof(basename));
3083 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3084 for (item = r_skinframe.hash[hashindex];item;item = item->next)
3085 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3089 rtexture_t *dyntexture;
3090 // check whether its a dynamic texture
3091 dyntexture = CL_GetDynTexture( basename );
3092 if (!add && !dyntexture)
3094 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3095 memset(item, 0, sizeof(*item));
3096 strlcpy(item->basename, basename, sizeof(item->basename));
3097 item->base = dyntexture; // either NULL or dyntexture handle
3098 item->textureflags = textureflags;
3099 item->comparewidth = comparewidth;
3100 item->compareheight = compareheight;
3101 item->comparecrc = comparecrc;
3102 item->next = r_skinframe.hash[hashindex];
3103 r_skinframe.hash[hashindex] = item;
3105 else if( item->base == NULL )
3107 rtexture_t *dyntexture;
3108 // check whether its a dynamic texture
3109 // 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]
3110 dyntexture = CL_GetDynTexture( basename );
3111 item->base = dyntexture; // either NULL or dyntexture handle
3114 R_SkinFrame_MarkUsed(item);
3118 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3120 unsigned long long avgcolor[5], wsum; \
3128 for(pix = 0; pix < cnt; ++pix) \
3131 for(comp = 0; comp < 3; ++comp) \
3133 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3136 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3138 for(comp = 0; comp < 3; ++comp) \
3139 avgcolor[comp] += getpixel * w; \
3142 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3143 avgcolor[4] += getpixel; \
3145 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3147 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3148 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3149 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3150 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3153 extern cvar_t gl_picmip;
3154 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3157 unsigned char *pixels;
3158 unsigned char *bumppixels;
3159 unsigned char *basepixels = NULL;
3160 int basepixels_width = 0;
3161 int basepixels_height = 0;
3162 skinframe_t *skinframe;
3163 rtexture_t *ddsbase = NULL;
3164 qboolean ddshasalpha = false;
3165 float ddsavgcolor[4];
3166 char basename[MAX_QPATH];
3167 int miplevel = R_PicmipForFlags(textureflags);
3168 int savemiplevel = miplevel;
3171 if (cls.state == ca_dedicated)
3174 // return an existing skinframe if already loaded
3175 // if loading of the first image fails, don't make a new skinframe as it
3176 // would cause all future lookups of this to be missing
3177 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3178 if (skinframe && skinframe->base)
3181 Image_StripImageExtension(name, basename, sizeof(basename));
3183 // check for DDS texture file first
3184 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3186 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3187 if (basepixels == NULL)
3191 // FIXME handle miplevel
3193 if (developer_loading.integer)
3194 Con_Printf("loading skin \"%s\"\n", name);
3196 // we've got some pixels to store, so really allocate this new texture now
3198 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3199 skinframe->stain = NULL;
3200 skinframe->merged = NULL;
3201 skinframe->base = NULL;
3202 skinframe->pants = NULL;
3203 skinframe->shirt = NULL;
3204 skinframe->nmap = NULL;
3205 skinframe->gloss = NULL;
3206 skinframe->glow = NULL;
3207 skinframe->fog = NULL;
3208 skinframe->reflect = NULL;
3209 skinframe->hasalpha = false;
3213 skinframe->base = ddsbase;
3214 skinframe->hasalpha = ddshasalpha;
3215 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3216 if (r_loadfog && skinframe->hasalpha)
3217 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3218 //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]);
3222 basepixels_width = image_width;
3223 basepixels_height = image_height;
3224 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);
3225 if (textureflags & TEXF_ALPHA)
3227 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3229 if (basepixels[j] < 255)
3231 skinframe->hasalpha = true;
3235 if (r_loadfog && skinframe->hasalpha)
3237 // has transparent pixels
3238 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3239 for (j = 0;j < image_width * image_height * 4;j += 4)
3244 pixels[j+3] = basepixels[j+3];
3246 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);
3250 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3251 //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]);
3252 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3253 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3254 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3255 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3260 mymiplevel = savemiplevel;
3261 if (r_loadnormalmap)
3262 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);
3263 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3265 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3266 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3267 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3268 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3271 // _norm is the name used by tenebrae and has been adopted as standard
3272 if (r_loadnormalmap && skinframe->nmap == NULL)
3274 mymiplevel = savemiplevel;
3275 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3277 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);
3281 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3283 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3284 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3285 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);
3287 Mem_Free(bumppixels);
3289 else if (r_shadow_bumpscale_basetexture.value > 0)
3291 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3292 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3293 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);
3296 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3297 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3300 // _luma is supported only for tenebrae compatibility
3301 // _glow is the preferred name
3302 mymiplevel = savemiplevel;
3303 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))))
3305 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);
3306 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3307 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3308 Mem_Free(pixels);pixels = NULL;
3311 mymiplevel = savemiplevel;
3312 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3314 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);
3315 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3316 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3321 mymiplevel = savemiplevel;
3322 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3324 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);
3325 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3326 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3331 mymiplevel = savemiplevel;
3332 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3334 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);
3335 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3336 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3341 mymiplevel = savemiplevel;
3342 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3344 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);
3345 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3346 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3352 Mem_Free(basepixels);
3357 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3358 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3361 unsigned char *temp1, *temp2;
3362 skinframe_t *skinframe;
3364 if (cls.state == ca_dedicated)
3367 // if already loaded just return it, otherwise make a new skinframe
3368 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3369 if (skinframe && skinframe->base)
3372 skinframe->stain = NULL;
3373 skinframe->merged = NULL;
3374 skinframe->base = NULL;
3375 skinframe->pants = NULL;
3376 skinframe->shirt = NULL;
3377 skinframe->nmap = NULL;
3378 skinframe->gloss = NULL;
3379 skinframe->glow = NULL;
3380 skinframe->fog = NULL;
3381 skinframe->reflect = NULL;
3382 skinframe->hasalpha = false;
3384 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3388 if (developer_loading.integer)
3389 Con_Printf("loading 32bit skin \"%s\"\n", name);
3391 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3393 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3394 temp2 = temp1 + width * height * 4;
3395 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3396 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);
3399 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3400 if (textureflags & TEXF_ALPHA)
3402 for (i = 3;i < width * height * 4;i += 4)
3404 if (skindata[i] < 255)
3406 skinframe->hasalpha = true;
3410 if (r_loadfog && skinframe->hasalpha)
3412 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3413 memcpy(fogpixels, skindata, width * height * 4);
3414 for (i = 0;i < width * height * 4;i += 4)
3415 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3416 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3417 Mem_Free(fogpixels);
3421 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3422 //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]);
3427 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3431 skinframe_t *skinframe;
3433 if (cls.state == ca_dedicated)
3436 // if already loaded just return it, otherwise make a new skinframe
3437 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3438 if (skinframe && skinframe->base)
3441 skinframe->stain = NULL;
3442 skinframe->merged = NULL;
3443 skinframe->base = NULL;
3444 skinframe->pants = NULL;
3445 skinframe->shirt = NULL;
3446 skinframe->nmap = NULL;
3447 skinframe->gloss = NULL;
3448 skinframe->glow = NULL;
3449 skinframe->fog = NULL;
3450 skinframe->reflect = NULL;
3451 skinframe->hasalpha = false;
3453 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3457 if (developer_loading.integer)
3458 Con_Printf("loading quake skin \"%s\"\n", name);
3460 // 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)
3461 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3462 memcpy(skinframe->qpixels, skindata, width*height);
3463 skinframe->qwidth = width;
3464 skinframe->qheight = height;
3467 for (i = 0;i < width * height;i++)
3468 featuresmask |= palette_featureflags[skindata[i]];
3470 skinframe->hasalpha = false;
3471 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3472 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3473 skinframe->qgeneratemerged = true;
3474 skinframe->qgeneratebase = skinframe->qhascolormapping;
3475 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3477 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3478 //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]);
3483 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3487 unsigned char *skindata;
3489 if (!skinframe->qpixels)
3492 if (!skinframe->qhascolormapping)
3493 colormapped = false;
3497 if (!skinframe->qgeneratebase)
3502 if (!skinframe->qgeneratemerged)
3506 width = skinframe->qwidth;
3507 height = skinframe->qheight;
3508 skindata = skinframe->qpixels;
3510 if (skinframe->qgeneratenmap)
3512 unsigned char *temp1, *temp2;
3513 skinframe->qgeneratenmap = false;
3514 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3515 temp2 = temp1 + width * height * 4;
3516 // use either a custom palette or the quake palette
3517 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3518 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3519 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);
3523 if (skinframe->qgenerateglow)
3525 skinframe->qgenerateglow = false;
3526 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
3531 skinframe->qgeneratebase = false;
3532 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);
3533 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);
3534 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);
3538 skinframe->qgeneratemerged = false;
3539 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);
3542 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3544 Mem_Free(skinframe->qpixels);
3545 skinframe->qpixels = NULL;
3549 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)
3552 skinframe_t *skinframe;
3554 if (cls.state == ca_dedicated)
3557 // if already loaded just return it, otherwise make a new skinframe
3558 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3559 if (skinframe && skinframe->base)
3562 skinframe->stain = NULL;
3563 skinframe->merged = NULL;
3564 skinframe->base = NULL;
3565 skinframe->pants = NULL;
3566 skinframe->shirt = NULL;
3567 skinframe->nmap = NULL;
3568 skinframe->gloss = NULL;
3569 skinframe->glow = NULL;
3570 skinframe->fog = NULL;
3571 skinframe->reflect = NULL;
3572 skinframe->hasalpha = false;
3574 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3578 if (developer_loading.integer)
3579 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3581 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3582 if (textureflags & TEXF_ALPHA)
3584 for (i = 0;i < width * height;i++)
3586 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3588 skinframe->hasalpha = true;
3592 if (r_loadfog && skinframe->hasalpha)
3593 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3596 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3597 //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]);
3602 skinframe_t *R_SkinFrame_LoadMissing(void)
3604 skinframe_t *skinframe;
3606 if (cls.state == ca_dedicated)
3609 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3610 skinframe->stain = NULL;
3611 skinframe->merged = NULL;
3612 skinframe->base = NULL;
3613 skinframe->pants = NULL;
3614 skinframe->shirt = NULL;
3615 skinframe->nmap = NULL;
3616 skinframe->gloss = NULL;
3617 skinframe->glow = NULL;
3618 skinframe->fog = NULL;
3619 skinframe->reflect = NULL;
3620 skinframe->hasalpha = false;
3622 skinframe->avgcolor[0] = rand() / RAND_MAX;
3623 skinframe->avgcolor[1] = rand() / RAND_MAX;
3624 skinframe->avgcolor[2] = rand() / RAND_MAX;
3625 skinframe->avgcolor[3] = 1;
3630 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3631 typedef struct suffixinfo_s
3634 qboolean flipx, flipy, flipdiagonal;
3637 static suffixinfo_t suffix[3][6] =
3640 {"px", false, false, false},
3641 {"nx", false, false, false},
3642 {"py", false, false, false},
3643 {"ny", false, false, false},
3644 {"pz", false, false, false},
3645 {"nz", false, false, false}
3648 {"posx", false, false, false},
3649 {"negx", false, false, false},
3650 {"posy", false, false, false},
3651 {"negy", false, false, false},
3652 {"posz", false, false, false},
3653 {"negz", false, false, false}
3656 {"rt", true, false, true},
3657 {"lf", false, true, true},
3658 {"ft", true, true, false},
3659 {"bk", false, false, false},
3660 {"up", true, false, true},
3661 {"dn", true, false, true}
3665 static int componentorder[4] = {0, 1, 2, 3};
3667 rtexture_t *R_LoadCubemap(const char *basename)
3669 int i, j, cubemapsize;
3670 unsigned char *cubemappixels, *image_buffer;
3671 rtexture_t *cubemaptexture;
3673 // must start 0 so the first loadimagepixels has no requested width/height
3675 cubemappixels = NULL;
3676 cubemaptexture = NULL;
3677 // keep trying different suffix groups (posx, px, rt) until one loads
3678 for (j = 0;j < 3 && !cubemappixels;j++)
3680 // load the 6 images in the suffix group
3681 for (i = 0;i < 6;i++)
3683 // generate an image name based on the base and and suffix
3684 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3686 if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3688 // an image loaded, make sure width and height are equal
3689 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3691 // if this is the first image to load successfully, allocate the cubemap memory
3692 if (!cubemappixels && image_width >= 1)
3694 cubemapsize = image_width;
3695 // note this clears to black, so unavailable sides are black
3696 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3698 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3700 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);
3703 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3705 Mem_Free(image_buffer);
3709 // if a cubemap loaded, upload it
3712 if (developer_loading.integer)
3713 Con_Printf("loading cubemap \"%s\"\n", basename);
3715 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);
3716 Mem_Free(cubemappixels);
3720 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3721 if (developer_loading.integer)
3723 Con_Printf("(tried tried images ");
3724 for (j = 0;j < 3;j++)
3725 for (i = 0;i < 6;i++)
3726 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3727 Con_Print(" and was unable to find any of them).\n");
3730 return cubemaptexture;
3733 rtexture_t *R_GetCubemap(const char *basename)
3736 for (i = 0;i < r_texture_numcubemaps;i++)
3737 if (r_texture_cubemaps[i] != NULL)
3738 if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3739 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3740 if (i >= MAX_CUBEMAPS || !r_main_mempool)
3741 return r_texture_whitecube;
3742 r_texture_numcubemaps++;
3743 r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3744 strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3745 r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3746 return r_texture_cubemaps[i]->texture;
3749 void R_FreeCubemap(const char *basename)
3753 for (i = 0;i < r_texture_numcubemaps;i++)
3755 if (r_texture_cubemaps[i] != NULL)
3757 if (r_texture_cubemaps[i]->texture)
3759 if (developer_loading.integer)
3760 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3761 R_FreeTexture(r_texture_cubemaps[i]->texture);
3762 Mem_Free(r_texture_cubemaps[i]);
3763 r_texture_cubemaps[i] = NULL;
3769 void R_FreeCubemaps(void)
3772 for (i = 0;i < r_texture_numcubemaps;i++)
3774 if (developer_loading.integer)
3775 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3776 if (r_texture_cubemaps[i] != NULL)
3778 if (r_texture_cubemaps[i]->texture)
3779 R_FreeTexture(r_texture_cubemaps[i]->texture);
3780 Mem_Free(r_texture_cubemaps[i]);
3783 r_texture_numcubemaps = 0;
3786 void R_Main_FreeViewCache(void)
3788 if (r_refdef.viewcache.entityvisible)
3789 Mem_Free(r_refdef.viewcache.entityvisible);
3790 if (r_refdef.viewcache.world_pvsbits)
3791 Mem_Free(r_refdef.viewcache.world_pvsbits);
3792 if (r_refdef.viewcache.world_leafvisible)
3793 Mem_Free(r_refdef.viewcache.world_leafvisible);
3794 if (r_refdef.viewcache.world_surfacevisible)
3795 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3796 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3799 void R_Main_ResizeViewCache(void)
3801 int numentities = r_refdef.scene.numentities;
3802 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3803 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3804 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3805 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3806 if (r_refdef.viewcache.maxentities < numentities)
3808 r_refdef.viewcache.maxentities = numentities;
3809 if (r_refdef.viewcache.entityvisible)
3810 Mem_Free(r_refdef.viewcache.entityvisible);
3811 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3813 if (r_refdef.viewcache.world_numclusters != numclusters)
3815 r_refdef.viewcache.world_numclusters = numclusters;
3816 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3817 if (r_refdef.viewcache.world_pvsbits)
3818 Mem_Free(r_refdef.viewcache.world_pvsbits);
3819 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3821 if (r_refdef.viewcache.world_numleafs != numleafs)
3823 r_refdef.viewcache.world_numleafs = numleafs;
3824 if (r_refdef.viewcache.world_leafvisible)
3825 Mem_Free(r_refdef.viewcache.world_leafvisible);
3826 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3828 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3830 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3831 if (r_refdef.viewcache.world_surfacevisible)
3832 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3833 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3837 extern rtexture_t *loadingscreentexture;
3838 void gl_main_start(void)
3840 loadingscreentexture = NULL;
3841 r_texture_blanknormalmap = NULL;
3842 r_texture_white = NULL;
3843 r_texture_grey128 = NULL;
3844 r_texture_black = NULL;
3845 r_texture_whitecube = NULL;
3846 r_texture_normalizationcube = NULL;
3847 r_texture_fogattenuation = NULL;
3848 r_texture_fogheighttexture = NULL;
3849 r_texture_gammaramps = NULL;
3850 r_texture_numcubemaps = 0;
3852 r_loaddds = r_texture_dds_load.integer != 0;
3853 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3855 switch(vid.renderpath)
3857 case RENDERPATH_GL20:
3858 case RENDERPATH_D3D9:
3859 case RENDERPATH_D3D10:
3860 case RENDERPATH_D3D11:
3861 case RENDERPATH_SOFT:
3862 case RENDERPATH_GLES2:
3863 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3864 Cvar_SetValueQuick(&gl_combine, 1);
3865 Cvar_SetValueQuick(&r_glsl, 1);
3866 r_loadnormalmap = true;
3870 case RENDERPATH_GL13:
3871 case RENDERPATH_GLES1:
3872 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3873 Cvar_SetValueQuick(&gl_combine, 1);
3874 Cvar_SetValueQuick(&r_glsl, 0);
3875 r_loadnormalmap = false;
3876 r_loadgloss = false;
3879 case RENDERPATH_GL11:
3880 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3881 Cvar_SetValueQuick(&gl_combine, 0);
3882 Cvar_SetValueQuick(&r_glsl, 0);
3883 r_loadnormalmap = false;
3884 r_loadgloss = false;
3890 R_FrameData_Reset();
3894 memset(r_queries, 0, sizeof(r_queries));
3896 r_qwskincache = NULL;
3897 r_qwskincache_size = 0;
3899 // due to caching of texture_t references, the collision cache must be reset
3900 Collision_Cache_Reset(true);
3902 // set up r_skinframe loading system for textures
3903 memset(&r_skinframe, 0, sizeof(r_skinframe));
3904 r_skinframe.loadsequence = 1;
3905 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3907 r_main_texturepool = R_AllocTexturePool();
3908 R_BuildBlankTextures();
3910 if (vid.support.arb_texture_cube_map)
3913 R_BuildNormalizationCube();
3915 r_texture_fogattenuation = NULL;
3916 r_texture_fogheighttexture = NULL;
3917 r_texture_gammaramps = NULL;
3918 //r_texture_fogintensity = NULL;
3919 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3920 memset(&r_waterstate, 0, sizeof(r_waterstate));
3921 r_glsl_permutation = NULL;
3922 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3923 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3924 glslshaderstring = NULL;
3926 r_hlsl_permutation = NULL;
3927 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3928 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
3930 hlslshaderstring = NULL;
3931 memset(&r_svbsp, 0, sizeof (r_svbsp));
3933 memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
3934 r_texture_numcubemaps = 0;
3936 r_refdef.fogmasktable_density = 0;
3939 void gl_main_shutdown(void)
3942 R_FrameData_Reset();
3944 R_Main_FreeViewCache();
3946 switch(vid.renderpath)
3948 case RENDERPATH_GL11:
3949 case RENDERPATH_GL13:
3950 case RENDERPATH_GL20:
3951 case RENDERPATH_GLES1:
3952 case RENDERPATH_GLES2:
3954 qglDeleteQueriesARB(r_maxqueries, r_queries);
3956 case RENDERPATH_D3D9:
3957 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3959 case RENDERPATH_D3D10:
3960 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3962 case RENDERPATH_D3D11:
3963 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3965 case RENDERPATH_SOFT:
3971 memset(r_queries, 0, sizeof(r_queries));
3973 r_qwskincache = NULL;
3974 r_qwskincache_size = 0;
3976 // clear out the r_skinframe state
3977 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3978 memset(&r_skinframe, 0, sizeof(r_skinframe));
3981 Mem_Free(r_svbsp.nodes);
3982 memset(&r_svbsp, 0, sizeof (r_svbsp));
3983 R_FreeTexturePool(&r_main_texturepool);
3984 loadingscreentexture = NULL;
3985 r_texture_blanknormalmap = NULL;
3986 r_texture_white = NULL;
3987 r_texture_grey128 = NULL;
3988 r_texture_black = NULL;
3989 r_texture_whitecube = NULL;
3990 r_texture_normalizationcube = NULL;
3991 r_texture_fogattenuation = NULL;
3992 r_texture_fogheighttexture = NULL;
3993 r_texture_gammaramps = NULL;
3994 r_texture_numcubemaps = 0;
3995 //r_texture_fogintensity = NULL;
3996 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3997 memset(&r_waterstate, 0, sizeof(r_waterstate));
4000 r_glsl_permutation = NULL;
4001 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4002 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4003 glslshaderstring = NULL;
4005 r_hlsl_permutation = NULL;
4006 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4007 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4009 hlslshaderstring = NULL;
4012 extern void CL_ParseEntityLump(char *entitystring);
4013 void gl_main_newmap(void)
4015 // FIXME: move this code to client
4016 char *entities, entname[MAX_QPATH];
4018 Mem_Free(r_qwskincache);
4019 r_qwskincache = NULL;
4020 r_qwskincache_size = 0;
4023 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4024 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4026 CL_ParseEntityLump(entities);
4030 if (cl.worldmodel->brush.entities)
4031 CL_ParseEntityLump(cl.worldmodel->brush.entities);
4033 R_Main_FreeViewCache();
4035 R_FrameData_Reset();
4038 void GL_Main_Init(void)
4040 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4042 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4043 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4044 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4045 if (gamemode == GAME_NEHAHRA)
4047 Cvar_RegisterVariable (&gl_fogenable);
4048 Cvar_RegisterVariable (&gl_fogdensity);
4049 Cvar_RegisterVariable (&gl_fogred);
4050 Cvar_RegisterVariable (&gl_foggreen);
4051 Cvar_RegisterVariable (&gl_fogblue);
4052 Cvar_RegisterVariable (&gl_fogstart);
4053 Cvar_RegisterVariable (&gl_fogend);
4054 Cvar_RegisterVariable (&gl_skyclip);
4056 Cvar_RegisterVariable(&r_motionblur);
4057 Cvar_RegisterVariable(&r_motionblur_maxblur);
4058 Cvar_RegisterVariable(&r_motionblur_bmin);
4059 Cvar_RegisterVariable(&r_motionblur_vmin);
4060 Cvar_RegisterVariable(&r_motionblur_vmax);
4061 Cvar_RegisterVariable(&r_motionblur_vcoeff);
4062 Cvar_RegisterVariable(&r_motionblur_randomize);
4063 Cvar_RegisterVariable(&r_damageblur);
4064 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4065 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4066 Cvar_RegisterVariable(&r_equalize_entities_by);
4067 Cvar_RegisterVariable(&r_equalize_entities_to);
4068 Cvar_RegisterVariable(&r_depthfirst);
4069 Cvar_RegisterVariable(&r_useinfinitefarclip);
4070 Cvar_RegisterVariable(&r_farclip_base);
4071 Cvar_RegisterVariable(&r_farclip_world);
4072 Cvar_RegisterVariable(&r_nearclip);
4073 Cvar_RegisterVariable(&r_deformvertexes);
4074 Cvar_RegisterVariable(&r_transparent);
4075 Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4076 Cvar_RegisterVariable(&r_showoverdraw);
4077 Cvar_RegisterVariable(&r_showbboxes);
4078 Cvar_RegisterVariable(&r_showsurfaces);
4079 Cvar_RegisterVariable(&r_showtris);
4080 Cvar_RegisterVariable(&r_shownormals);
4081 Cvar_RegisterVariable(&r_showlighting);
4082 Cvar_RegisterVariable(&r_showshadowvolumes);
4083 Cvar_RegisterVariable(&r_showcollisionbrushes);
4084 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4085 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4086 Cvar_RegisterVariable(&r_showdisabledepthtest);
4087 Cvar_RegisterVariable(&r_drawportals);
4088 Cvar_RegisterVariable(&r_drawentities);
4089 Cvar_RegisterVariable(&r_draw2d);
4090 Cvar_RegisterVariable(&r_drawworld);
4091 Cvar_RegisterVariable(&r_cullentities_trace);
4092 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4093 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4094 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4095 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4096 Cvar_RegisterVariable(&r_drawviewmodel);
4097 Cvar_RegisterVariable(&r_drawexteriormodel);
4098 Cvar_RegisterVariable(&r_speeds);
4099 Cvar_RegisterVariable(&r_fullbrights);
4100 Cvar_RegisterVariable(&r_wateralpha);
4101 Cvar_RegisterVariable(&r_dynamic);
4102 Cvar_RegisterVariable(&r_fakelight);
4103 Cvar_RegisterVariable(&r_fakelight_intensity);
4104 Cvar_RegisterVariable(&r_fullbright);
4105 Cvar_RegisterVariable(&r_shadows);
4106 Cvar_RegisterVariable(&r_shadows_darken);
4107 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4108 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4109 Cvar_RegisterVariable(&r_shadows_throwdistance);
4110 Cvar_RegisterVariable(&r_shadows_throwdirection);
4111 Cvar_RegisterVariable(&r_shadows_focus);
4112 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4113 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4114 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4115 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4116 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4117 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4118 Cvar_RegisterVariable(&r_fog_exp2);
4119 Cvar_RegisterVariable(&r_fog_clear);
4120 Cvar_RegisterVariable(&r_drawfog);
4121 Cvar_RegisterVariable(&r_transparentdepthmasking);
4122 Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4123 Cvar_RegisterVariable(&r_transparent_sortarraysize);
4124 Cvar_RegisterVariable(&r_texture_dds_load);
4125 Cvar_RegisterVariable(&r_texture_dds_save);
4126 Cvar_RegisterVariable(&r_textureunits);
4127 Cvar_RegisterVariable(&gl_combine);
4128 Cvar_RegisterVariable(&r_viewfbo);
4129 Cvar_RegisterVariable(&r_viewscale);
4130 Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4131 Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4132 Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4133 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4134 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4135 Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4136 Cvar_RegisterVariable(&r_glsl);
4137 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4138 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4139 Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4140 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4141 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4142 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4143 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4144 Cvar_RegisterVariable(&r_glsl_postprocess);
4145 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4146 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4147 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4148 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4149 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4150 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4151 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4152 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4154 Cvar_RegisterVariable(&r_water);
4155 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4156 Cvar_RegisterVariable(&r_water_clippingplanebias);
4157 Cvar_RegisterVariable(&r_water_refractdistort);
4158 Cvar_RegisterVariable(&r_water_reflectdistort);
4159 Cvar_RegisterVariable(&r_water_scissormode);
4160 Cvar_RegisterVariable(&r_water_lowquality);
4162 Cvar_RegisterVariable(&r_lerpsprites);
4163 Cvar_RegisterVariable(&r_lerpmodels);
4164 Cvar_RegisterVariable(&r_lerplightstyles);
4165 Cvar_RegisterVariable(&r_waterscroll);
4166 Cvar_RegisterVariable(&r_bloom);
4167 Cvar_RegisterVariable(&r_bloom_colorscale);
4168 Cvar_RegisterVariable(&r_bloom_brighten);
4169 Cvar_RegisterVariable(&r_bloom_blur);
4170 Cvar_RegisterVariable(&r_bloom_resolution);
4171 Cvar_RegisterVariable(&r_bloom_colorexponent);
4172 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4173 Cvar_RegisterVariable(&r_hdr);
4174 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4175 Cvar_RegisterVariable(&r_hdr_glowintensity);
4176 Cvar_RegisterVariable(&r_hdr_range);
4177 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4178 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4179 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4180 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4181 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4182 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4183 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4184 Cvar_RegisterVariable(&developer_texturelogging);
4185 Cvar_RegisterVariable(&gl_lightmaps);
4186 Cvar_RegisterVariable(&r_test);
4187 Cvar_RegisterVariable(&r_glsl_saturation);
4188 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4189 Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4190 Cvar_RegisterVariable(&r_framedatasize);
4191 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4192 Cvar_SetValue("r_fullbrights", 0);
4193 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4196 extern void R_Textures_Init(void);
4197 extern void GL_Draw_Init(void);
4198 extern void GL_Main_Init(void);
4199 extern void R_Shadow_Init(void);
4200 extern void R_Sky_Init(void);
4201 extern void GL_Surf_Init(void);
4202 extern void R_Particles_Init(void);
4203 extern void R_Explosion_Init(void);
4204 extern void gl_backend_init(void);
4205 extern void Sbar_Init(void);
4206 extern void R_LightningBeams_Init(void);
4207 extern void Mod_RenderInit(void);
4208 extern void Font_Init(void);
4210 void Render_Init(void)
4223 R_LightningBeams_Init();
4232 extern char *ENGINE_EXTENSIONS;
4235 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4236 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4237 gl_version = (const char *)qglGetString(GL_VERSION);
4238 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4242 if (!gl_platformextensions)
4243 gl_platformextensions = "";
4245 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4246 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4247 Con_Printf("GL_VERSION: %s\n", gl_version);
4248 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4249 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4251 VID_CheckExtensions();
4253 // LordHavoc: report supported extensions
4254 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4256 // clear to black (loading plaque will be seen over this)
4257 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4260 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4264 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4266 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4269 p = r_refdef.view.frustum + i;
4274 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4278 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4282 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4286 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4290 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4294 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4298 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4302 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4310 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4314 for (i = 0;i < numplanes;i++)
4321 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4325 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4329 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4333 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4337 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4341 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4345 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4349 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4357 //==================================================================================
4359 // LordHavoc: this stores temporary data used within the same frame
4361 typedef struct r_framedata_mem_s
4363 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4364 size_t size; // how much usable space
4365 size_t current; // how much space in use
4366 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4367 size_t wantedsize; // how much space was allocated
4368 unsigned char *data; // start of real data (16byte aligned)
4372 static r_framedata_mem_t *r_framedata_mem;
4374 void R_FrameData_Reset(void)
4376 while (r_framedata_mem)
4378 r_framedata_mem_t *next = r_framedata_mem->purge;
4379 Mem_Free(r_framedata_mem);
4380 r_framedata_mem = next;
4384 void R_FrameData_Resize(void)
4387 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4388 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4389 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4391 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4392 newmem->wantedsize = wantedsize;
4393 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4394 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4395 newmem->current = 0;
4397 newmem->purge = r_framedata_mem;
4398 r_framedata_mem = newmem;
4402 void R_FrameData_NewFrame(void)
4404 R_FrameData_Resize();
4405 if (!r_framedata_mem)
4407 // if we ran out of space on the last frame, free the old memory now
4408 while (r_framedata_mem->purge)
4410 // repeatedly remove the second item in the list, leaving only head
4411 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4412 Mem_Free(r_framedata_mem->purge);
4413 r_framedata_mem->purge = next;
4415 // reset the current mem pointer
4416 r_framedata_mem->current = 0;
4417 r_framedata_mem->mark = 0;
4420 void *R_FrameData_Alloc(size_t size)
4424 // align to 16 byte boundary - the data pointer is already aligned, so we
4425 // only need to ensure the size of every allocation is also aligned
4426 size = (size + 15) & ~15;
4428 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4430 // emergency - we ran out of space, allocate more memory
4431 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4432 R_FrameData_Resize();
4435 data = r_framedata_mem->data + r_framedata_mem->current;
4436 r_framedata_mem->current += size;
4438 // count the usage for stats
4439 r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4440 r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4442 return (void *)data;
4445 void *R_FrameData_Store(size_t size, void *data)
4447 void *d = R_FrameData_Alloc(size);
4449 memcpy(d, data, size);
4453 void R_FrameData_SetMark(void)
4455 if (!r_framedata_mem)
4457 r_framedata_mem->mark = r_framedata_mem->current;
4460 void R_FrameData_ReturnToMark(void)
4462 if (!r_framedata_mem)
4464 r_framedata_mem->current = r_framedata_mem->mark;
4467 //==================================================================================
4469 // LordHavoc: animcache originally written by Echon, rewritten since then
4472 * Animation cache prevents re-generating mesh data for an animated model
4473 * multiple times in one frame for lighting, shadowing, reflections, etc.
4476 void R_AnimCache_Free(void)
4480 void R_AnimCache_ClearCache(void)
4483 entity_render_t *ent;
4485 for (i = 0;i < r_refdef.scene.numentities;i++)
4487 ent = r_refdef.scene.entities[i];
4488 ent->animcache_vertex3f = NULL;
4489 ent->animcache_normal3f = NULL;
4490 ent->animcache_svector3f = NULL;
4491 ent->animcache_tvector3f = NULL;
4492 ent->animcache_vertexmesh = NULL;
4493 ent->animcache_vertex3fbuffer = NULL;
4494 ent->animcache_vertexmeshbuffer = NULL;
4498 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4502 // check if we need the meshbuffers
4503 if (!vid.useinterleavedarrays)
4506 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4507 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4508 // TODO: upload vertex3f buffer?
4509 if (ent->animcache_vertexmesh)
4511 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4512 for (i = 0;i < numvertices;i++)
4513 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4514 if (ent->animcache_svector3f)
4515 for (i = 0;i < numvertices;i++)
4516 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4517 if (ent->animcache_tvector3f)
4518 for (i = 0;i < numvertices;i++)
4519 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4520 if (ent->animcache_normal3f)
4521 for (i = 0;i < numvertices;i++)
4522 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4523 // TODO: upload vertexmeshbuffer?
4527 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4529 dp_model_t *model = ent->model;
4531 // see if it's already cached this frame
4532 if (ent->animcache_vertex3f)
4534 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4535 if (wantnormals || wanttangents)
4537 if (ent->animcache_normal3f)
4538 wantnormals = false;
4539 if (ent->animcache_svector3f)
4540 wanttangents = false;
4541 if (wantnormals || wanttangents)
4543 numvertices = model->surfmesh.num_vertices;
4545 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4548 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4549 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4551 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4552 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4558 // see if this ent is worth caching
4559 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4561 // get some memory for this entity and generate mesh data
4562 numvertices = model->surfmesh.num_vertices;
4563 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4565 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4568 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4569 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4571 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4572 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4577 void R_AnimCache_CacheVisibleEntities(void)
4580 qboolean wantnormals = true;
4581 qboolean wanttangents = !r_showsurfaces.integer;
4583 switch(vid.renderpath)
4585 case RENDERPATH_GL20:
4586 case RENDERPATH_D3D9:
4587 case RENDERPATH_D3D10:
4588 case RENDERPATH_D3D11:
4589 case RENDERPATH_GLES2:
4591 case RENDERPATH_GL11:
4592 case RENDERPATH_GL13:
4593 case RENDERPATH_GLES1:
4594 wanttangents = false;
4596 case RENDERPATH_SOFT:
4600 if (r_shownormals.integer)
4601 wanttangents = wantnormals = true;
4603 // TODO: thread this
4604 // NOTE: R_PrepareRTLights() also caches entities
4606 for (i = 0;i < r_refdef.scene.numentities;i++)
4607 if (r_refdef.viewcache.entityvisible[i])
4608 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4611 //==================================================================================
4613 extern cvar_t r_overheadsprites_pushback;
4615 static void R_View_UpdateEntityLighting (void)
4618 entity_render_t *ent;
4619 vec3_t tempdiffusenormal, avg;
4620 vec_t f, fa, fd, fdd;
4621 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4623 for (i = 0;i < r_refdef.scene.numentities;i++)
4625 ent = r_refdef.scene.entities[i];
4627 // skip unseen models
4628 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4632 if (ent->model && ent->model->brush.num_leafs)
4634 // TODO: use modellight for r_ambient settings on world?
4635 VectorSet(ent->modellight_ambient, 0, 0, 0);
4636 VectorSet(ent->modellight_diffuse, 0, 0, 0);
4637 VectorSet(ent->modellight_lightdir, 0, 0, 1);
4641 // fetch the lighting from the worldmodel data
4642 VectorClear(ent->modellight_ambient);
4643 VectorClear(ent->modellight_diffuse);
4644 VectorClear(tempdiffusenormal);
4645 if (ent->flags & RENDER_LIGHT)
4648 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4650 // complete lightning for lit sprites
4651 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4652 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4654 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4655 org[2] = org[2] + r_overheadsprites_pushback.value;
4656 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4659 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4661 if(ent->flags & RENDER_EQUALIZE)
4663 // first fix up ambient lighting...
4664 if(r_equalize_entities_minambient.value > 0)
4666 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4669 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4670 if(fa < r_equalize_entities_minambient.value * fd)
4673 // fa'/fd' = minambient
4674 // fa'+0.25*fd' = fa+0.25*fd
4676 // fa' = fd' * minambient
4677 // fd'*(0.25+minambient) = fa+0.25*fd
4679 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4680 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4682 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4683 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
4684 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4685 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4690 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4692 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4693 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4697 // adjust brightness and saturation to target
4698 avg[0] = avg[1] = avg[2] = fa / f;
4699 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4700 avg[0] = avg[1] = avg[2] = fd / f;
4701 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4707 VectorSet(ent->modellight_ambient, 1, 1, 1);
4709 // move the light direction into modelspace coordinates for lighting code
4710 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4711 if(VectorLength2(ent->modellight_lightdir) == 0)
4712 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4713 VectorNormalize(ent->modellight_lightdir);
4717 #define MAX_LINEOFSIGHTTRACES 64
4719 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4722 vec3_t boxmins, boxmaxs;
4725 dp_model_t *model = r_refdef.scene.worldmodel;
4727 if (!model || !model->brush.TraceLineOfSight)
4730 // expand the box a little
4731 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4732 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4733 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4734 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4735 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4736 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4738 // return true if eye is inside enlarged box
4739 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4743 VectorCopy(eye, start);
4744 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4745 if (model->brush.TraceLineOfSight(model, start, end))
4748 // try various random positions
4749 for (i = 0;i < numsamples;i++)
4751 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4752 if (model->brush.TraceLineOfSight(model, start, end))
4760 static void R_View_UpdateEntityVisible (void)
4765 entity_render_t *ent;
4767 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4768 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4769 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
4770 : RENDER_EXTERIORMODEL;
4771 if (!r_drawviewmodel.integer)
4772 renderimask |= RENDER_VIEWMODEL;
4773 if (!r_drawexteriormodel.integer)
4774 renderimask |= RENDER_EXTERIORMODEL;
4775 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4777 // worldmodel can check visibility
4778 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4779 for (i = 0;i < r_refdef.scene.numentities;i++)
4781 ent = r_refdef.scene.entities[i];
4782 if (!(ent->flags & renderimask))
4783 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)))
4784 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))
4785 r_refdef.viewcache.entityvisible[i] = true;
4790 // no worldmodel or it can't check visibility
4791 for (i = 0;i < r_refdef.scene.numentities;i++)
4793 ent = r_refdef.scene.entities[i];
4794 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));
4797 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
4798 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4800 for (i = 0;i < r_refdef.scene.numentities;i++)
4802 if (!r_refdef.viewcache.entityvisible[i])
4804 ent = r_refdef.scene.entities[i];
4805 if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4807 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4809 continue; // temp entities do pvs only
4810 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4811 ent->last_trace_visibility = realtime;
4812 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4813 r_refdef.viewcache.entityvisible[i] = 0;
4819 /// only used if skyrendermasked, and normally returns false
4820 int R_DrawBrushModelsSky (void)
4823 entity_render_t *ent;
4826 for (i = 0;i < r_refdef.scene.numentities;i++)
4828 if (!r_refdef.viewcache.entityvisible[i])
4830 ent = r_refdef.scene.entities[i];
4831 if (!ent->model || !ent->model->DrawSky)
4833 ent->model->DrawSky(ent);
4839 static void R_DrawNoModel(entity_render_t *ent);
4840 static void R_DrawModels(void)
4843 entity_render_t *ent;
4845 for (i = 0;i < r_refdef.scene.numentities;i++)
4847 if (!r_refdef.viewcache.entityvisible[i])
4849 ent = r_refdef.scene.entities[i];
4850 r_refdef.stats.entities++;
4852 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
4855 Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
4856 Con_Printf("R_DrawModels\n");
4857 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]);
4858 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);
4859 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);
4862 if (ent->model && ent->model->Draw != NULL)
4863 ent->model->Draw(ent);
4869 static void R_DrawModelsDepth(void)
4872 entity_render_t *ent;
4874 for (i = 0;i < r_refdef.scene.numentities;i++)
4876 if (!r_refdef.viewcache.entityvisible[i])
4878 ent = r_refdef.scene.entities[i];
4879 if (ent->model && ent->model->DrawDepth != NULL)
4880 ent->model->DrawDepth(ent);
4884 static void R_DrawModelsDebug(void)
4887 entity_render_t *ent;
4889 for (i = 0;i < r_refdef.scene.numentities;i++)
4891 if (!r_refdef.viewcache.entityvisible[i])
4893 ent = r_refdef.scene.entities[i];
4894 if (ent->model && ent->model->DrawDebug != NULL)
4895 ent->model->DrawDebug(ent);
4899 static void R_DrawModelsAddWaterPlanes(void)
4902 entity_render_t *ent;
4904 for (i = 0;i < r_refdef.scene.numentities;i++)
4906 if (!r_refdef.viewcache.entityvisible[i])
4908 ent = r_refdef.scene.entities[i];
4909 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4910 ent->model->DrawAddWaterPlanes(ent);
4914 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4916 if (r_hdr_irisadaptation.integer)
4920 vec3_t diffusenormal;
4925 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4926 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
4927 brightness = max(0.0000001f, brightness);
4928 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4929 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4930 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
4931 current = r_hdr_irisadaptation_value.value;
4933 current = min(current + adjust, goal);
4934 else if (current > goal)
4935 current = max(current - adjust, goal);
4936 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4937 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4939 else if (r_hdr_irisadaptation_value.value != 1.0f)
4940 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4943 static void R_View_SetFrustum(const int *scissor)
4946 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
4947 vec3_t forward, left, up, origin, v;
4951 // flipped x coordinates (because x points left here)
4952 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4953 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4955 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
4956 switch(vid.renderpath)
4958 case RENDERPATH_D3D9:
4959 case RENDERPATH_D3D10:
4960 case RENDERPATH_D3D11:
4961 // non-flipped y coordinates
4962 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4963 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4965 case RENDERPATH_SOFT:
4966 case RENDERPATH_GL11:
4967 case RENDERPATH_GL13:
4968 case RENDERPATH_GL20:
4969 case RENDERPATH_GLES1:
4970 case RENDERPATH_GLES2:
4971 // non-flipped y coordinates
4972 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4973 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4978 // we can't trust r_refdef.view.forward and friends in reflected scenes
4979 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4982 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4983 r_refdef.view.frustum[0].normal[1] = 0 - 0;
4984 r_refdef.view.frustum[0].normal[2] = -1 - 0;
4985 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4986 r_refdef.view.frustum[1].normal[1] = 0 + 0;
4987 r_refdef.view.frustum[1].normal[2] = -1 + 0;
4988 r_refdef.view.frustum[2].normal[0] = 0 - 0;
4989 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4990 r_refdef.view.frustum[2].normal[2] = -1 - 0;
4991 r_refdef.view.frustum[3].normal[0] = 0 + 0;
4992 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4993 r_refdef.view.frustum[3].normal[2] = -1 + 0;
4997 zNear = r_refdef.nearclip;
4998 nudge = 1.0 - 1.0 / (1<<23);
4999 r_refdef.view.frustum[4].normal[0] = 0 - 0;
5000 r_refdef.view.frustum[4].normal[1] = 0 - 0;
5001 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5002 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5003 r_refdef.view.frustum[5].normal[0] = 0 + 0;
5004 r_refdef.view.frustum[5].normal[1] = 0 + 0;
5005 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5006 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5012 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5013 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5014 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5015 r_refdef.view.frustum[0].dist = m[15] - m[12];
5017 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5018 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5019 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5020 r_refdef.view.frustum[1].dist = m[15] + m[12];
5022 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5023 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5024 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5025 r_refdef.view.frustum[2].dist = m[15] - m[13];
5027 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5028 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5029 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5030 r_refdef.view.frustum[3].dist = m[15] + m[13];
5032 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5033 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5034 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5035 r_refdef.view.frustum[4].dist = m[15] - m[14];
5037 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5038 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5039 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5040 r_refdef.view.frustum[5].dist = m[15] + m[14];
5043 if (r_refdef.view.useperspective)
5045 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5046 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]);
5047 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]);
5048 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]);
5049 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]);
5051 // then the normals from the corners relative to origin
5052 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5053 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5054 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5055 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5057 // in a NORMAL view, forward cross left == up
5058 // in a REFLECTED view, forward cross left == down
5059 // so our cross products above need to be adjusted for a left handed coordinate system
5060 CrossProduct(forward, left, v);
5061 if(DotProduct(v, up) < 0)
5063 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5064 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5065 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5066 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5069 // Leaving those out was a mistake, those were in the old code, and they
5070 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5071 // I couldn't reproduce it after adding those normalizations. --blub
5072 VectorNormalize(r_refdef.view.frustum[0].normal);
5073 VectorNormalize(r_refdef.view.frustum[1].normal);
5074 VectorNormalize(r_refdef.view.frustum[2].normal);
5075 VectorNormalize(r_refdef.view.frustum[3].normal);
5077 // make the corners absolute
5078 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5079 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5080 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5081 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5084 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5086 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5087 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5088 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5089 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5090 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5094 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5095 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5096 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5097 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5098 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5099 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5100 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5101 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5102 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5103 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5105 r_refdef.view.numfrustumplanes = 5;
5107 if (r_refdef.view.useclipplane)
5109 r_refdef.view.numfrustumplanes = 6;
5110 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5113 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5114 PlaneClassify(r_refdef.view.frustum + i);
5116 // LordHavoc: note to all quake engine coders, Quake had a special case
5117 // for 90 degrees which assumed a square view (wrong), so I removed it,
5118 // Quake2 has it disabled as well.
5120 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5121 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5122 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5123 //PlaneClassify(&frustum[0]);
5125 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5126 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5127 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5128 //PlaneClassify(&frustum[1]);
5130 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5131 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5132 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5133 //PlaneClassify(&frustum[2]);
5135 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5136 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5137 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5138 //PlaneClassify(&frustum[3]);
5141 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5142 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5143 //PlaneClassify(&frustum[4]);
5146 void R_View_UpdateWithScissor(const int *myscissor)
5148 R_Main_ResizeViewCache();
5149 R_View_SetFrustum(myscissor);
5150 R_View_WorldVisibility(r_refdef.view.useclipplane);
5151 R_View_UpdateEntityVisible();
5152 R_View_UpdateEntityLighting();
5155 void R_View_Update(void)
5157 R_Main_ResizeViewCache();
5158 R_View_SetFrustum(NULL);
5159 R_View_WorldVisibility(r_refdef.view.useclipplane);
5160 R_View_UpdateEntityVisible();
5161 R_View_UpdateEntityLighting();
5164 float viewscalefpsadjusted = 1.0f;
5166 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5168 float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5169 scale = bound(0.03125f, scale, 1.0f);
5170 *outwidth = (int)ceil(width * scale);
5171 *outheight = (int)ceil(height * scale);
5174 void R_Mesh_SetMainRenderTargets(void)
5176 if (r_bloomstate.fbo_framebuffer)
5177 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5179 R_Mesh_ResetRenderTargets();
5182 void R_SetupView(qboolean allowwaterclippingplane)
5184 const float *customclipplane = NULL;
5186 int scaledwidth, scaledheight;
5187 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5189 // LordHavoc: couldn't figure out how to make this approach the
5190 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5191 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5192 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5193 dist = r_refdef.view.clipplane.dist;
5194 plane[0] = r_refdef.view.clipplane.normal[0];
5195 plane[1] = r_refdef.view.clipplane.normal[1];
5196 plane[2] = r_refdef.view.clipplane.normal[2];
5198 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5201 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5202 if (!r_refdef.view.useperspective)
5203 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);
5204 else if (vid.stencil && r_useinfinitefarclip.integer)
5205 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);
5207 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);
5208 R_Mesh_SetMainRenderTargets();
5209 R_SetViewport(&r_refdef.view.viewport);
5210 if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5212 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5213 float screenplane[4];
5214 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5215 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5216 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5217 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5218 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5222 void R_EntityMatrix(const matrix4x4_t *matrix)
5224 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5226 gl_modelmatrixchanged = false;
5227 gl_modelmatrix = *matrix;
5228 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5229 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5230 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5231 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5233 switch(vid.renderpath)
5235 case RENDERPATH_D3D9:
5237 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5238 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5241 case RENDERPATH_D3D10:
5242 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5244 case RENDERPATH_D3D11:
5245 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5247 case RENDERPATH_GL11:
5248 case RENDERPATH_GL13:
5249 case RENDERPATH_GLES1:
5250 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5252 case RENDERPATH_SOFT:
5253 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5254 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5256 case RENDERPATH_GL20:
5257 case RENDERPATH_GLES2:
5258 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5259 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5265 void R_ResetViewRendering2D(void)
5267 r_viewport_t viewport;
5270 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5271 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);
5272 R_Mesh_ResetRenderTargets();
5273 R_SetViewport(&viewport);
5274 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5275 GL_Color(1, 1, 1, 1);
5276 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5277 GL_BlendFunc(GL_ONE, GL_ZERO);
5278 GL_ScissorTest(false);
5279 GL_DepthMask(false);
5280 GL_DepthRange(0, 1);
5281 GL_DepthTest(false);
5282 GL_DepthFunc(GL_LEQUAL);
5283 R_EntityMatrix(&identitymatrix);
5284 R_Mesh_ResetTextureState();
5285 GL_PolygonOffset(0, 0);
5286 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5287 switch(vid.renderpath)
5289 case RENDERPATH_GL11:
5290 case RENDERPATH_GL13:
5291 case RENDERPATH_GL20:
5292 case RENDERPATH_GLES1:
5293 case RENDERPATH_GLES2:
5294 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5296 case RENDERPATH_D3D9:
5297 case RENDERPATH_D3D10:
5298 case RENDERPATH_D3D11:
5299 case RENDERPATH_SOFT:
5302 GL_CullFace(GL_NONE);
5305 void R_ResetViewRendering3D(void)
5310 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5311 GL_Color(1, 1, 1, 1);
5312 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5313 GL_BlendFunc(GL_ONE, GL_ZERO);
5314 GL_ScissorTest(true);
5316 GL_DepthRange(0, 1);
5318 GL_DepthFunc(GL_LEQUAL);
5319 R_EntityMatrix(&identitymatrix);
5320 R_Mesh_ResetTextureState();
5321 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5322 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5323 switch(vid.renderpath)
5325 case RENDERPATH_GL11:
5326 case RENDERPATH_GL13:
5327 case RENDERPATH_GL20:
5328 case RENDERPATH_GLES1:
5329 case RENDERPATH_GLES2:
5330 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5332 case RENDERPATH_D3D9:
5333 case RENDERPATH_D3D10:
5334 case RENDERPATH_D3D11:
5335 case RENDERPATH_SOFT:
5338 GL_CullFace(r_refdef.view.cullface_back);
5343 R_RenderView_UpdateViewVectors
5346 static void R_RenderView_UpdateViewVectors(void)
5348 // break apart the view matrix into vectors for various purposes
5349 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5350 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5351 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5352 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5353 // make an inverted copy of the view matrix for tracking sprites
5354 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5357 void R_RenderScene(void);
5358 void R_RenderWaterPlanes(void);
5360 static void R_Water_StartFrame(void)
5363 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5364 r_waterstate_waterplane_t *p;
5366 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5369 switch(vid.renderpath)
5371 case RENDERPATH_GL20:
5372 case RENDERPATH_D3D9:
5373 case RENDERPATH_D3D10:
5374 case RENDERPATH_D3D11:
5375 case RENDERPATH_SOFT:
5376 case RENDERPATH_GLES2:
5378 case RENDERPATH_GL11:
5379 case RENDERPATH_GL13:
5380 case RENDERPATH_GLES1:
5384 // set waterwidth and waterheight to the water resolution that will be
5385 // used (often less than the screen resolution for faster rendering)
5386 R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5388 // calculate desired texture sizes
5389 // can't use water if the card does not support the texture size
5390 if (!r_water.integer || r_showsurfaces.integer)
5391 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5392 else if (vid.support.arb_texture_non_power_of_two)
5394 texturewidth = waterwidth;
5395 textureheight = waterheight;
5396 camerawidth = waterwidth;
5397 cameraheight = waterheight;
5401 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5402 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5403 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
5404 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
5407 // allocate textures as needed
5408 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5410 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5411 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5413 if (p->texture_refraction)
5414 R_FreeTexture(p->texture_refraction);
5415 p->texture_refraction = NULL;
5416 if (p->texture_reflection)
5417 R_FreeTexture(p->texture_reflection);
5418 p->texture_reflection = NULL;
5419 if (p->texture_camera)
5420 R_FreeTexture(p->texture_camera);
5421 p->texture_camera = NULL;
5423 memset(&r_waterstate, 0, sizeof(r_waterstate));
5424 r_waterstate.texturewidth = texturewidth;
5425 r_waterstate.textureheight = textureheight;
5426 r_waterstate.camerawidth = camerawidth;
5427 r_waterstate.cameraheight = cameraheight;
5430 if (r_waterstate.texturewidth)
5432 int scaledwidth, scaledheight;
5434 r_waterstate.enabled = true;
5436 // when doing a reduced render (HDR) we want to use a smaller area
5437 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5438 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5439 R_GetScaledViewSize(r_waterstate.waterwidth, r_waterstate.waterheight, &scaledwidth, &scaledheight);
5441 // set up variables that will be used in shader setup
5442 r_waterstate.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5443 r_waterstate.screenscale[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5444 r_waterstate.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5445 r_waterstate.screencenter[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5448 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5449 r_waterstate.numwaterplanes = 0;
5452 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5454 int triangleindex, planeindex;
5460 r_waterstate_waterplane_t *p;
5461 texture_t *t = R_GetCurrentTexture(surface->texture);
5463 // just use the first triangle with a valid normal for any decisions
5464 VectorClear(normal);
5465 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5467 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5468 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5469 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5470 TriangleNormal(vert[0], vert[1], vert[2], normal);
5471 if (VectorLength2(normal) >= 0.001)
5475 VectorCopy(normal, plane.normal);
5476 VectorNormalize(plane.normal);
5477 plane.dist = DotProduct(vert[0], plane.normal);
5478 PlaneClassify(&plane);
5479 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5481 // skip backfaces (except if nocullface is set)
5482 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5484 VectorNegate(plane.normal, plane.normal);
5486 PlaneClassify(&plane);
5490 // find a matching plane if there is one
5491 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5492 if(p->camera_entity == t->camera_entity)
5493 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5495 if (planeindex >= r_waterstate.maxwaterplanes)
5496 return; // nothing we can do, out of planes
5498 // if this triangle does not fit any known plane rendered this frame, add one
5499 if (planeindex >= r_waterstate.numwaterplanes)
5501 // store the new plane
5502 r_waterstate.numwaterplanes++;
5504 // clear materialflags and pvs
5505 p->materialflags = 0;
5506 p->pvsvalid = false;
5507 p->camera_entity = t->camera_entity;
5508 VectorCopy(surface->mins, p->mins);
5509 VectorCopy(surface->maxs, p->maxs);
5514 p->mins[0] = min(p->mins[0], surface->mins[0]);
5515 p->mins[1] = min(p->mins[1], surface->mins[1]);
5516 p->mins[2] = min(p->mins[2], surface->mins[2]);
5517 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5518 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5519 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5521 // merge this surface's materialflags into the waterplane
5522 p->materialflags |= t->currentmaterialflags;
5523 if(!(p->materialflags & MATERIALFLAG_CAMERA))
5525 // merge this surface's PVS into the waterplane
5526 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5527 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5528 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5530 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5536 extern cvar_t r_drawparticles;
5537 extern cvar_t r_drawdecals;
5539 static void R_Water_ProcessPlanes(void)
5542 r_refdef_view_t originalview;
5543 r_refdef_view_t myview;
5544 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;
5545 r_waterstate_waterplane_t *p;
5548 originalview = r_refdef.view;
5550 // lowquality hack, temporarily shut down some cvars and restore afterwards
5551 qualityreduction = r_water_lowquality.integer;
5552 if (qualityreduction > 0)
5554 if (qualityreduction >= 1)
5556 old_r_shadows = r_shadows.integer;
5557 old_r_worldrtlight = r_shadow_realtime_world.integer;
5558 old_r_dlight = r_shadow_realtime_dlight.integer;
5559 Cvar_SetValueQuick(&r_shadows, 0);
5560 Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5561 Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5563 if (qualityreduction >= 2)
5565 old_r_dynamic = r_dynamic.integer;
5566 old_r_particles = r_drawparticles.integer;
5567 old_r_decals = r_drawdecals.integer;
5568 Cvar_SetValueQuick(&r_dynamic, 0);
5569 Cvar_SetValueQuick(&r_drawparticles, 0);
5570 Cvar_SetValueQuick(&r_drawdecals, 0);
5574 // make sure enough textures are allocated
5575 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5577 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5579 if (!p->texture_refraction)
5580 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);
5581 if (!p->texture_refraction)
5584 else if (p->materialflags & MATERIALFLAG_CAMERA)
5586 if (!p->texture_camera)
5587 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);
5588 if (!p->texture_camera)
5592 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5594 if (!p->texture_reflection)
5595 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);
5596 if (!p->texture_reflection)
5602 r_refdef.view = originalview;
5603 r_refdef.view.showdebug = false;
5604 r_refdef.view.width = r_waterstate.waterwidth;
5605 r_refdef.view.height = r_waterstate.waterheight;
5606 r_refdef.view.useclipplane = true;
5607 myview = r_refdef.view;
5608 r_waterstate.renderingscene = true;
5609 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5611 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5613 r_refdef.view = myview;
5614 if(r_water_scissormode.integer)
5617 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5618 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5621 // render reflected scene and copy into texture
5622 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5623 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5624 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5625 r_refdef.view.clipplane = p->plane;
5626 // reverse the cullface settings for this render
5627 r_refdef.view.cullface_front = GL_FRONT;
5628 r_refdef.view.cullface_back = GL_BACK;
5629 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5631 r_refdef.view.usecustompvs = true;
5633 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5635 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5638 R_ResetViewRendering3D();
5639 R_ClearScreen(r_refdef.fogenabled);
5640 if(r_water_scissormode.integer & 2)
5641 R_View_UpdateWithScissor(myscissor);
5644 if(r_water_scissormode.integer & 1)
5645 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5648 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);
5651 // render the normal view scene and copy into texture
5652 // (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)
5653 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5655 r_refdef.view = myview;
5656 if(r_water_scissormode.integer)
5659 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5660 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5663 r_waterstate.renderingrefraction = true;
5665 r_refdef.view.clipplane = p->plane;
5666 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5667 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5669 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5671 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5672 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5673 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5674 R_RenderView_UpdateViewVectors();
5675 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5677 r_refdef.view.usecustompvs = true;
5678 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);
5682 PlaneClassify(&r_refdef.view.clipplane);
5684 R_ResetViewRendering3D();
5685 R_ClearScreen(r_refdef.fogenabled);
5686 if(r_water_scissormode.integer & 2)
5687 R_View_UpdateWithScissor(myscissor);
5690 if(r_water_scissormode.integer & 1)
5691 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5694 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);
5695 r_waterstate.renderingrefraction = false;
5697 else if (p->materialflags & MATERIALFLAG_CAMERA)
5699 r_refdef.view = myview;
5701 r_refdef.view.clipplane = p->plane;
5702 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5703 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5705 r_refdef.view.width = r_waterstate.camerawidth;
5706 r_refdef.view.height = r_waterstate.cameraheight;
5707 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5708 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5710 if(p->camera_entity)
5712 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5713 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5716 // note: all of the view is used for displaying... so
5717 // there is no use in scissoring
5719 // reverse the cullface settings for this render
5720 r_refdef.view.cullface_front = GL_FRONT;
5721 r_refdef.view.cullface_back = GL_BACK;
5722 // also reverse the view matrix
5723 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
5724 R_RenderView_UpdateViewVectors();
5725 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5727 r_refdef.view.usecustompvs = true;
5728 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);
5731 // camera needs no clipplane
5732 r_refdef.view.useclipplane = false;
5734 PlaneClassify(&r_refdef.view.clipplane);
5736 R_ResetViewRendering3D();
5737 R_ClearScreen(r_refdef.fogenabled);
5741 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);
5742 r_waterstate.renderingrefraction = false;
5746 if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5747 r_waterstate.renderingscene = false;
5748 r_refdef.view = originalview;
5749 R_ResetViewRendering3D();
5750 R_ClearScreen(r_refdef.fogenabled);
5754 r_refdef.view = originalview;
5755 r_waterstate.renderingscene = false;
5756 Cvar_SetValueQuick(&r_water, 0);
5757 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
5759 // lowquality hack, restore cvars
5760 if (qualityreduction > 0)
5762 if (qualityreduction >= 1)
5764 Cvar_SetValueQuick(&r_shadows, old_r_shadows);
5765 Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
5766 Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
5768 if (qualityreduction >= 2)
5770 Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
5771 Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
5772 Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
5777 void R_Bloom_StartFrame(void)
5779 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5780 int viewwidth, viewheight;
5783 if (r_viewscale_fpsscaling.integer)
5785 double actualframetime;
5786 double targetframetime;
5788 actualframetime = r_refdef.lastdrawscreentime;
5789 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5790 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5791 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5792 if (r_viewscale_fpsscaling_stepsize.value > 0)
5793 adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5794 viewscalefpsadjusted += adjust;
5795 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5798 viewscalefpsadjusted = 1.0f;
5800 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5802 switch(vid.renderpath)
5804 case RENDERPATH_GL20:
5805 case RENDERPATH_D3D9:
5806 case RENDERPATH_D3D10:
5807 case RENDERPATH_D3D11:
5808 case RENDERPATH_SOFT:
5809 case RENDERPATH_GLES2:
5811 case RENDERPATH_GL11:
5812 case RENDERPATH_GL13:
5813 case RENDERPATH_GLES1:
5817 // set bloomwidth and bloomheight to the bloom resolution that will be
5818 // used (often less than the screen resolution for faster rendering)
5819 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5820 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5821 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5822 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5823 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5825 // calculate desired texture sizes
5826 if (vid.support.arb_texture_non_power_of_two)
5828 screentexturewidth = vid.width;
5829 screentextureheight = vid.height;
5830 bloomtexturewidth = r_bloomstate.bloomwidth;
5831 bloomtextureheight = r_bloomstate.bloomheight;
5835 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
5836 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
5837 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
5838 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
5841 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))
5843 Cvar_SetValueQuick(&r_hdr, 0);
5844 Cvar_SetValueQuick(&r_bloom, 0);
5845 Cvar_SetValueQuick(&r_motionblur, 0);
5846 Cvar_SetValueQuick(&r_damageblur, 0);
5849 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)
5850 screentexturewidth = screentextureheight = 0;
5851 if (!r_hdr.integer && !r_bloom.integer)
5852 bloomtexturewidth = bloomtextureheight = 0;
5854 textype = TEXTYPE_COLORBUFFER;
5855 switch (vid.renderpath)
5857 case RENDERPATH_GL20:
5858 case RENDERPATH_GLES2:
5859 if (vid.support.ext_framebuffer_object)
5861 if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5862 if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5865 case RENDERPATH_GL11:
5866 case RENDERPATH_GL13:
5867 case RENDERPATH_GLES1:
5868 case RENDERPATH_D3D9:
5869 case RENDERPATH_D3D10:
5870 case RENDERPATH_D3D11:
5871 case RENDERPATH_SOFT:
5875 // allocate textures as needed
5876 if (r_bloomstate.screentexturewidth != screentexturewidth
5877 || r_bloomstate.screentextureheight != screentextureheight
5878 || r_bloomstate.bloomtexturewidth != bloomtexturewidth
5879 || r_bloomstate.bloomtextureheight != bloomtextureheight
5880 || r_bloomstate.texturetype != textype
5881 || r_bloomstate.viewfbo != r_viewfbo.integer)
5883 if (r_bloomstate.texture_bloom)
5884 R_FreeTexture(r_bloomstate.texture_bloom);
5885 r_bloomstate.texture_bloom = NULL;
5886 if (r_bloomstate.texture_screen)
5887 R_FreeTexture(r_bloomstate.texture_screen);
5888 r_bloomstate.texture_screen = NULL;
5889 if (r_bloomstate.fbo_framebuffer)
5890 R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
5891 r_bloomstate.fbo_framebuffer = 0;
5892 if (r_bloomstate.texture_framebuffercolor)
5893 R_FreeTexture(r_bloomstate.texture_framebuffercolor);
5894 r_bloomstate.texture_framebuffercolor = NULL;
5895 if (r_bloomstate.texture_framebufferdepth)
5896 R_FreeTexture(r_bloomstate.texture_framebufferdepth);
5897 r_bloomstate.texture_framebufferdepth = NULL;
5898 r_bloomstate.screentexturewidth = screentexturewidth;
5899 r_bloomstate.screentextureheight = screentextureheight;
5900 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5901 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);
5902 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
5904 // FIXME: choose depth bits based on a cvar
5905 r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
5906 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);
5907 r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5908 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5909 // render depth into one texture and normalmap into the other
5913 qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5914 qglReadBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5915 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
5916 if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
5917 Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
5920 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5921 r_bloomstate.bloomtextureheight = bloomtextureheight;
5922 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5923 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);
5924 r_bloomstate.viewfbo = r_viewfbo.integer;
5925 r_bloomstate.texturetype = textype;
5928 // when doing a reduced render (HDR) we want to use a smaller area
5929 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5930 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5931 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5932 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5933 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5935 // set up a texcoord array for the full resolution screen image
5936 // (we have to keep this around to copy back during final render)
5937 r_bloomstate.screentexcoord2f[0] = 0;
5938 r_bloomstate.screentexcoord2f[1] = (float)viewheight / (float)r_bloomstate.screentextureheight;
5939 r_bloomstate.screentexcoord2f[2] = (float)viewwidth / (float)r_bloomstate.screentexturewidth;
5940 r_bloomstate.screentexcoord2f[3] = (float)viewheight / (float)r_bloomstate.screentextureheight;
5941 r_bloomstate.screentexcoord2f[4] = (float)viewwidth / (float)r_bloomstate.screentexturewidth;
5942 r_bloomstate.screentexcoord2f[5] = 0;
5943 r_bloomstate.screentexcoord2f[6] = 0;
5944 r_bloomstate.screentexcoord2f[7] = 0;
5946 // set up a texcoord array for the reduced resolution bloom image
5947 // (which will be additive blended over the screen image)
5948 r_bloomstate.bloomtexcoord2f[0] = 0;
5949 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5950 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5951 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5952 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5953 r_bloomstate.bloomtexcoord2f[5] = 0;
5954 r_bloomstate.bloomtexcoord2f[6] = 0;
5955 r_bloomstate.bloomtexcoord2f[7] = 0;
5957 switch(vid.renderpath)
5959 case RENDERPATH_GL11:
5960 case RENDERPATH_GL13:
5961 case RENDERPATH_GL20:
5962 case RENDERPATH_SOFT:
5963 case RENDERPATH_GLES1:
5964 case RENDERPATH_GLES2:
5966 case RENDERPATH_D3D9:
5967 case RENDERPATH_D3D10:
5968 case RENDERPATH_D3D11:
5971 for (i = 0;i < 4;i++)
5973 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
5974 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
5975 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
5976 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
5982 if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth)
5984 r_bloomstate.enabled = true;
5985 r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer;
5988 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);
5990 if (r_bloomstate.fbo_framebuffer)
5991 r_refdef.view.clear = true;
5994 void R_Bloom_CopyBloomTexture(float colorscale)
5996 r_refdef.stats.bloom++;
5998 // scale down screen texture to the bloom texture size
6000 R_Mesh_SetMainRenderTargets();
6001 R_SetViewport(&r_bloomstate.viewport);
6002 GL_BlendFunc(GL_ONE, GL_ZERO);
6003 GL_Color(colorscale, colorscale, colorscale, 1);
6004 // 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...
6005 switch(vid.renderpath)
6007 case RENDERPATH_GL11:
6008 case RENDERPATH_GL13:
6009 case RENDERPATH_GL20:
6010 case RENDERPATH_GLES1:
6011 case RENDERPATH_GLES2:
6012 case RENDERPATH_SOFT:
6013 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6015 case RENDERPATH_D3D9:
6016 case RENDERPATH_D3D10:
6017 case RENDERPATH_D3D11:
6018 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6021 // TODO: do boxfilter scale-down in shader?
6022 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6023 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6024 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6026 // we now have a bloom image in the framebuffer
6027 // copy it into the bloom image texture for later processing
6028 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);
6029 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6032 void R_Bloom_CopyHDRTexture(void)
6034 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);
6035 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6038 void R_Bloom_MakeTexture(void)
6041 float xoffset, yoffset, r, brighten;
6043 r_refdef.stats.bloom++;
6045 R_ResetViewRendering2D();
6047 // we have a bloom image in the framebuffer
6049 R_SetViewport(&r_bloomstate.viewport);
6051 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6054 r = bound(0, r_bloom_colorexponent.value / x, 1);
6055 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6057 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
6058 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
6059 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6060 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6062 // copy the vertically blurred bloom view to a texture
6063 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);
6064 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6067 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
6068 brighten = r_bloom_brighten.value;
6069 if (r_bloomstate.hdr)
6070 brighten *= r_hdr_range.value;
6071 brighten = sqrt(brighten);
6073 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6074 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
6076 for (dir = 0;dir < 2;dir++)
6078 // blend on at multiple vertical offsets to achieve a vertical blur
6079 // TODO: do offset blends using GLSL
6080 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6081 GL_BlendFunc(GL_ONE, GL_ZERO);
6082 for (x = -range;x <= range;x++)
6084 if (!dir){xoffset = 0;yoffset = x;}
6085 else {xoffset = x;yoffset = 0;}
6086 xoffset /= (float)r_bloomstate.bloomtexturewidth;
6087 yoffset /= (float)r_bloomstate.bloomtextureheight;
6088 // compute a texcoord array with the specified x and y offset
6089 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
6090 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6091 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6092 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6093 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6094 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
6095 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
6096 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
6097 // this r value looks like a 'dot' particle, fading sharply to
6098 // black at the edges
6099 // (probably not realistic but looks good enough)
6100 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6101 //r = brighten/(range*2+1);
6102 r = brighten / (range * 2 + 1);
6104 r *= (1 - x*x/(float)(range*range));
6105 GL_Color(r, r, r, 1);
6106 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6107 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6108 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6109 GL_BlendFunc(GL_ONE, GL_ONE);
6112 // copy the vertically blurred bloom view to a texture
6113 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);
6114 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6118 void R_HDR_RenderBloomTexture(void)
6120 int oldwidth, oldheight;
6121 float oldcolorscale;
6122 qboolean oldwaterstate;
6124 oldwaterstate = r_waterstate.enabled;
6125 oldcolorscale = r_refdef.view.colorscale;
6126 oldwidth = r_refdef.view.width;
6127 oldheight = r_refdef.view.height;
6128 r_refdef.view.width = r_bloomstate.bloomwidth;
6129 r_refdef.view.height = r_bloomstate.bloomheight;
6131 if(r_hdr.integer < 2)
6132 r_waterstate.enabled = false;
6134 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
6135 // TODO: add exposure compensation features
6136 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6138 r_refdef.view.showdebug = false;
6139 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6141 R_ResetViewRendering3D();
6143 R_ClearScreen(r_refdef.fogenabled);
6144 if (r_timereport_active)
6145 R_TimeReport("HDRclear");
6148 if (r_timereport_active)
6149 R_TimeReport("visibility");
6151 // only do secondary renders with HDR if r_hdr is 2 or higher
6152 r_waterstate.numwaterplanes = 0;
6153 if (r_waterstate.enabled)
6154 R_RenderWaterPlanes();
6156 r_refdef.view.showdebug = true;
6158 r_waterstate.numwaterplanes = 0;
6160 R_ResetViewRendering2D();
6162 R_Bloom_CopyHDRTexture();
6163 R_Bloom_MakeTexture();
6165 // restore the view settings
6166 r_waterstate.enabled = oldwaterstate;
6167 r_refdef.view.width = oldwidth;
6168 r_refdef.view.height = oldheight;
6169 r_refdef.view.colorscale = oldcolorscale;
6171 R_ResetViewRendering3D();
6173 R_ClearScreen(r_refdef.fogenabled);
6174 if (r_timereport_active)
6175 R_TimeReport("viewclear");
6178 static void R_BlendView(void)
6180 unsigned int permutation;
6181 float uservecs[4][4];
6183 switch (vid.renderpath)
6185 case RENDERPATH_GL20:
6186 case RENDERPATH_D3D9:
6187 case RENDERPATH_D3D10:
6188 case RENDERPATH_D3D11:
6189 case RENDERPATH_SOFT:
6190 case RENDERPATH_GLES2:
6192 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6193 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6194 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6195 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6196 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6198 if (r_bloomstate.texture_screen)
6200 // make sure the buffer is available
6201 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6203 R_ResetViewRendering2D();
6204 R_Mesh_SetMainRenderTargets();
6206 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6208 // declare variables
6210 static float avgspeed;
6212 speed = VectorLength(cl.movement_velocity);
6214 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
6215 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
6217 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
6218 speed = bound(0, speed, 1);
6219 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
6221 // calculate values into a standard alpha
6222 cl.motionbluralpha = 1 - exp(-
6224 (r_motionblur.value * speed / 80)
6226 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6229 max(0.0001, cl.time - cl.oldtime) // fps independent
6232 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6233 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6235 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6237 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6238 GL_Color(1, 1, 1, cl.motionbluralpha);
6239 switch(vid.renderpath)
6241 case RENDERPATH_GL11:
6242 case RENDERPATH_GL13:
6243 case RENDERPATH_GL20:
6244 case RENDERPATH_GLES1:
6245 case RENDERPATH_GLES2:
6246 case RENDERPATH_SOFT:
6247 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6249 case RENDERPATH_D3D9:
6250 case RENDERPATH_D3D10:
6251 case RENDERPATH_D3D11:
6252 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6255 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6256 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6257 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6261 // copy view into the screen texture
6262 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);
6263 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6265 else if (!r_bloomstate.texture_bloom)
6267 // we may still have to do view tint...
6268 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6270 // apply a color tint to the whole view
6271 R_ResetViewRendering2D();
6272 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6273 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6274 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6275 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6276 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6278 break; // no screen processing, no bloom, skip it
6281 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6283 // render simple bloom effect
6284 // copy the screen and shrink it and darken it for the bloom process
6285 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6286 // make the bloom texture
6287 R_Bloom_MakeTexture();
6290 #if _MSC_VER >= 1400
6291 #define sscanf sscanf_s
6293 memset(uservecs, 0, sizeof(uservecs));
6294 if (r_glsl_postprocess_uservec1_enable.integer)
6295 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6296 if (r_glsl_postprocess_uservec2_enable.integer)
6297 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6298 if (r_glsl_postprocess_uservec3_enable.integer)
6299 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6300 if (r_glsl_postprocess_uservec4_enable.integer)
6301 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6303 R_ResetViewRendering2D();
6304 GL_Color(1, 1, 1, 1);
6305 GL_BlendFunc(GL_ONE, GL_ZERO);
6307 switch(vid.renderpath)
6309 case RENDERPATH_GL20:
6310 case RENDERPATH_GLES2:
6311 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6312 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6313 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_bloomstate.texture_screen);
6314 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_bloomstate.texture_bloom );
6315 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6316 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]);
6317 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6318 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]);
6319 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]);
6320 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]);
6321 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]);
6322 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6323 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6324 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);
6326 case RENDERPATH_D3D9:
6328 // 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...
6329 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6330 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6331 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6332 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6333 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6334 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6335 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6336 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6337 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6338 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6339 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6340 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6341 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6342 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6345 case RENDERPATH_D3D10:
6346 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6348 case RENDERPATH_D3D11:
6349 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6351 case RENDERPATH_SOFT:
6352 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6353 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6354 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6355 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6356 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6357 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6358 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6359 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6360 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6361 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6362 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6363 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6364 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6365 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6370 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6371 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6373 case RENDERPATH_GL11:
6374 case RENDERPATH_GL13:
6375 case RENDERPATH_GLES1:
6376 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6378 // apply a color tint to the whole view
6379 R_ResetViewRendering2D();
6380 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6381 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6382 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6383 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6384 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6390 matrix4x4_t r_waterscrollmatrix;
6392 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6394 if (r_refdef.fog_density)
6396 r_refdef.fogcolor[0] = r_refdef.fog_red;
6397 r_refdef.fogcolor[1] = r_refdef.fog_green;
6398 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6400 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6401 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6402 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6403 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6407 VectorCopy(r_refdef.fogcolor, fogvec);
6408 // color.rgb *= ContrastBoost * SceneBrightness;
6409 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6410 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6411 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6412 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6417 void R_UpdateVariables(void)
6421 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6423 r_refdef.farclip = r_farclip_base.value;
6424 if (r_refdef.scene.worldmodel)
6425 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6426 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6428 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6429 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6430 r_refdef.polygonfactor = 0;
6431 r_refdef.polygonoffset = 0;
6432 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6433 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6435 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6436 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6437 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6438 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6439 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6440 if (FAKELIGHT_ENABLED)
6442 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6444 if (r_showsurfaces.integer)
6446 r_refdef.scene.rtworld = false;
6447 r_refdef.scene.rtworldshadows = false;
6448 r_refdef.scene.rtdlight = false;
6449 r_refdef.scene.rtdlightshadows = false;
6450 r_refdef.lightmapintensity = 0;
6453 if (gamemode == GAME_NEHAHRA)
6455 if (gl_fogenable.integer)
6457 r_refdef.oldgl_fogenable = true;
6458 r_refdef.fog_density = gl_fogdensity.value;
6459 r_refdef.fog_red = gl_fogred.value;
6460 r_refdef.fog_green = gl_foggreen.value;
6461 r_refdef.fog_blue = gl_fogblue.value;
6462 r_refdef.fog_alpha = 1;
6463 r_refdef.fog_start = 0;
6464 r_refdef.fog_end = gl_skyclip.value;
6465 r_refdef.fog_height = 1<<30;
6466 r_refdef.fog_fadedepth = 128;
6468 else if (r_refdef.oldgl_fogenable)
6470 r_refdef.oldgl_fogenable = false;
6471 r_refdef.fog_density = 0;
6472 r_refdef.fog_red = 0;
6473 r_refdef.fog_green = 0;
6474 r_refdef.fog_blue = 0;
6475 r_refdef.fog_alpha = 0;
6476 r_refdef.fog_start = 0;
6477 r_refdef.fog_end = 0;
6478 r_refdef.fog_height = 1<<30;
6479 r_refdef.fog_fadedepth = 128;
6483 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6484 r_refdef.fog_start = max(0, r_refdef.fog_start);
6485 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6487 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6489 if (r_refdef.fog_density && r_drawfog.integer)
6491 r_refdef.fogenabled = true;
6492 // this is the point where the fog reaches 0.9986 alpha, which we
6493 // consider a good enough cutoff point for the texture
6494 // (0.9986 * 256 == 255.6)
6495 if (r_fog_exp2.integer)
6496 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6498 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6499 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6500 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6501 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6502 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6503 R_BuildFogHeightTexture();
6504 // fog color was already set
6505 // update the fog texture
6506 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)
6507 R_BuildFogTexture();
6508 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6509 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6512 r_refdef.fogenabled = false;
6514 switch(vid.renderpath)
6516 case RENDERPATH_GL20:
6517 case RENDERPATH_D3D9:
6518 case RENDERPATH_D3D10:
6519 case RENDERPATH_D3D11:
6520 case RENDERPATH_SOFT:
6521 case RENDERPATH_GLES2:
6522 if(v_glslgamma.integer && !vid_gammatables_trivial)
6524 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6526 // build GLSL gamma texture
6527 #define RAMPWIDTH 256
6528 unsigned short ramp[RAMPWIDTH * 3];
6529 unsigned char rampbgr[RAMPWIDTH][4];
6532 r_texture_gammaramps_serial = vid_gammatables_serial;
6534 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6535 for(i = 0; i < RAMPWIDTH; ++i)
6537 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6538 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6539 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6542 if (r_texture_gammaramps)
6544 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6548 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6554 // remove GLSL gamma texture
6557 case RENDERPATH_GL11:
6558 case RENDERPATH_GL13:
6559 case RENDERPATH_GLES1:
6564 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6565 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6571 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6572 if( scenetype != r_currentscenetype ) {
6573 // store the old scenetype
6574 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6575 r_currentscenetype = scenetype;
6576 // move in the new scene
6577 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6586 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6588 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6589 if( scenetype == r_currentscenetype ) {
6590 return &r_refdef.scene;
6592 return &r_scenes_store[ scenetype ];
6601 int dpsoftrast_test;
6602 void R_RenderView(void)
6604 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6606 dpsoftrast_test = r_test.integer;
6608 if (r_timereport_active)
6609 R_TimeReport("start");
6610 r_textureframe++; // used only by R_GetCurrentTexture
6611 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6613 if(R_CompileShader_CheckStaticParms())
6616 if (!r_drawentities.integer)
6617 r_refdef.scene.numentities = 0;
6619 R_AnimCache_ClearCache();
6620 R_FrameData_NewFrame();
6622 /* adjust for stereo display */
6623 if(R_Stereo_Active())
6625 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);
6626 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6629 if (r_refdef.view.isoverlay)
6631 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6632 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6633 R_TimeReport("depthclear");
6635 r_refdef.view.showdebug = false;
6637 r_waterstate.enabled = false;
6638 r_waterstate.numwaterplanes = 0;
6642 r_refdef.view.matrix = originalmatrix;
6648 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6650 r_refdef.view.matrix = originalmatrix;
6651 return; //Host_Error ("R_RenderView: NULL worldmodel");
6654 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6656 R_RenderView_UpdateViewVectors();
6658 R_Shadow_UpdateWorldLightSelection();
6660 R_Bloom_StartFrame();
6661 R_Water_StartFrame();
6664 if (r_timereport_active)
6665 R_TimeReport("viewsetup");
6667 R_ResetViewRendering3D();
6669 if (r_refdef.view.clear || r_refdef.fogenabled)
6671 R_ClearScreen(r_refdef.fogenabled);
6672 if (r_timereport_active)
6673 R_TimeReport("viewclear");
6675 r_refdef.view.clear = true;
6677 // this produces a bloom texture to be used in R_BlendView() later
6678 if (r_bloomstate.hdr)
6680 R_HDR_RenderBloomTexture();
6681 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6682 r_textureframe++; // used only by R_GetCurrentTexture
6685 r_refdef.view.showdebug = true;
6688 if (r_timereport_active)
6689 R_TimeReport("visibility");
6691 r_waterstate.numwaterplanes = 0;
6692 if (r_waterstate.enabled)
6693 R_RenderWaterPlanes();
6696 r_waterstate.numwaterplanes = 0;
6699 if (r_timereport_active)
6700 R_TimeReport("blendview");
6702 GL_Scissor(0, 0, vid.width, vid.height);
6703 GL_ScissorTest(false);
6705 r_refdef.view.matrix = originalmatrix;
6710 void R_RenderWaterPlanes(void)
6712 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6714 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6715 if (r_timereport_active)
6716 R_TimeReport("waterworld");
6719 // don't let sound skip if going slow
6720 if (r_refdef.scene.extraupdate)
6723 R_DrawModelsAddWaterPlanes();
6724 if (r_timereport_active)
6725 R_TimeReport("watermodels");
6727 if (r_waterstate.numwaterplanes)
6729 R_Water_ProcessPlanes();
6730 if (r_timereport_active)
6731 R_TimeReport("waterscenes");
6735 extern void R_DrawLightningBeams (void);
6736 extern void VM_CL_AddPolygonsToMeshQueue (void);
6737 extern void R_DrawPortals (void);
6738 extern cvar_t cl_locs_show;
6739 static void R_DrawLocs(void);
6740 static void R_DrawEntityBBoxes(void);
6741 static void R_DrawModelDecals(void);
6742 extern void R_DrawModelShadows(void);
6743 extern void R_DrawModelShadowMaps(void);
6744 extern cvar_t cl_decals_newsystem;
6745 extern qboolean r_shadow_usingdeferredprepass;
6746 void R_RenderScene(void)
6748 qboolean shadowmapping = false;
6750 if (r_timereport_active)
6751 R_TimeReport("beginscene");
6753 r_refdef.stats.renders++;
6757 // don't let sound skip if going slow
6758 if (r_refdef.scene.extraupdate)
6761 R_MeshQueue_BeginScene();
6765 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);
6767 if (r_timereport_active)
6768 R_TimeReport("skystartframe");
6770 if (cl.csqc_vidvars.drawworld)
6772 // don't let sound skip if going slow
6773 if (r_refdef.scene.extraupdate)
6776 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6778 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6779 if (r_timereport_active)
6780 R_TimeReport("worldsky");
6783 if (R_DrawBrushModelsSky() && r_timereport_active)
6784 R_TimeReport("bmodelsky");
6786 if (skyrendermasked && skyrenderlater)
6788 // we have to force off the water clipping plane while rendering sky
6792 if (r_timereport_active)
6793 R_TimeReport("sky");
6797 R_AnimCache_CacheVisibleEntities();
6798 if (r_timereport_active)
6799 R_TimeReport("animation");
6801 R_Shadow_PrepareLights();
6802 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6803 R_Shadow_PrepareModelShadows();
6804 if (r_timereport_active)
6805 R_TimeReport("preparelights");
6807 if (R_Shadow_ShadowMappingEnabled())
6808 shadowmapping = true;
6810 if (r_shadow_usingdeferredprepass)
6811 R_Shadow_DrawPrepass();
6813 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6815 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6816 if (r_timereport_active)
6817 R_TimeReport("worlddepth");
6819 if (r_depthfirst.integer >= 2)
6821 R_DrawModelsDepth();
6822 if (r_timereport_active)
6823 R_TimeReport("modeldepth");
6826 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6828 R_DrawModelShadowMaps();
6829 R_ResetViewRendering3D();
6830 // don't let sound skip if going slow
6831 if (r_refdef.scene.extraupdate)
6835 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6837 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6838 if (r_timereport_active)
6839 R_TimeReport("world");
6842 // don't let sound skip if going slow
6843 if (r_refdef.scene.extraupdate)
6847 if (r_timereport_active)
6848 R_TimeReport("models");
6850 // don't let sound skip if going slow
6851 if (r_refdef.scene.extraupdate)
6854 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6856 R_DrawModelShadows();
6857 R_ResetViewRendering3D();
6858 // don't let sound skip if going slow
6859 if (r_refdef.scene.extraupdate)
6863 if (!r_shadow_usingdeferredprepass)
6865 R_Shadow_DrawLights();
6866 if (r_timereport_active)
6867 R_TimeReport("rtlights");
6870 // don't let sound skip if going slow
6871 if (r_refdef.scene.extraupdate)
6874 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6876 R_DrawModelShadows();
6877 R_ResetViewRendering3D();
6878 // don't let sound skip if going slow
6879 if (r_refdef.scene.extraupdate)
6883 if (cl.csqc_vidvars.drawworld)
6885 if (cl_decals_newsystem.integer)
6887 R_DrawModelDecals();
6888 if (r_timereport_active)
6889 R_TimeReport("modeldecals");
6894 if (r_timereport_active)
6895 R_TimeReport("decals");
6899 if (r_timereport_active)
6900 R_TimeReport("particles");
6903 if (r_timereport_active)
6904 R_TimeReport("explosions");
6906 R_DrawLightningBeams();
6907 if (r_timereport_active)
6908 R_TimeReport("lightning");
6911 VM_CL_AddPolygonsToMeshQueue();
6913 if (r_refdef.view.showdebug)
6915 if (cl_locs_show.integer)
6918 if (r_timereport_active)
6919 R_TimeReport("showlocs");
6922 if (r_drawportals.integer)
6925 if (r_timereport_active)
6926 R_TimeReport("portals");
6929 if (r_showbboxes.value > 0)
6931 R_DrawEntityBBoxes();
6932 if (r_timereport_active)
6933 R_TimeReport("bboxes");
6937 if (r_transparent.integer)
6939 R_MeshQueue_RenderTransparent();
6940 if (r_timereport_active)
6941 R_TimeReport("drawtrans");
6944 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))
6946 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6947 if (r_timereport_active)
6948 R_TimeReport("worlddebug");
6949 R_DrawModelsDebug();
6950 if (r_timereport_active)
6951 R_TimeReport("modeldebug");
6954 if (cl.csqc_vidvars.drawworld)
6956 R_Shadow_DrawCoronas();
6957 if (r_timereport_active)
6958 R_TimeReport("coronas");
6963 GL_DepthTest(false);
6964 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6965 GL_Color(1, 1, 1, 1);
6966 qglBegin(GL_POLYGON);
6967 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6968 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6969 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6970 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
6972 qglBegin(GL_POLYGON);
6973 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]);
6974 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]);
6975 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]);
6976 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]);
6978 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
6982 // don't let sound skip if going slow
6983 if (r_refdef.scene.extraupdate)
6986 R_ResetViewRendering2D();
6989 static const unsigned short bboxelements[36] =
6999 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7002 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7004 RSurf_ActiveWorldEntity();
7006 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7007 GL_DepthMask(false);
7008 GL_DepthRange(0, 1);
7009 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7010 // R_Mesh_ResetTextureState();
7012 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7013 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7014 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7015 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7016 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7017 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7018 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7019 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7020 R_FillColors(color4f, 8, cr, cg, cb, ca);
7021 if (r_refdef.fogenabled)
7023 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7025 f1 = RSurf_FogVertex(v);
7027 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7028 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7029 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7032 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7033 R_Mesh_ResetTextureState();
7034 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7035 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7038 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7042 prvm_edict_t *edict;
7043 prvm_prog_t *prog_save = prog;
7045 // this function draws bounding boxes of server entities
7049 GL_CullFace(GL_NONE);
7050 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7054 for (i = 0;i < numsurfaces;i++)
7056 edict = PRVM_EDICT_NUM(surfacelist[i]);
7057 switch ((int)edict->fields.server->solid)
7059 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
7060 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
7061 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
7062 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7063 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
7064 default: Vector4Set(color, 0, 0, 0, 0.50);break;
7066 color[3] *= r_showbboxes.value;
7067 color[3] = bound(0, color[3], 1);
7068 GL_DepthTest(!r_showdisabledepthtest.integer);
7069 GL_CullFace(r_refdef.view.cullface_front);
7070 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7076 static void R_DrawEntityBBoxes(void)
7079 prvm_edict_t *edict;
7081 prvm_prog_t *prog_save = prog;
7083 // this function draws bounding boxes of server entities
7089 for (i = 0;i < prog->num_edicts;i++)
7091 edict = PRVM_EDICT_NUM(i);
7092 if (edict->priv.server->free)
7094 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7095 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7097 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7099 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7100 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7106 static const int nomodelelement3i[24] =
7118 static const unsigned short nomodelelement3s[24] =
7130 static const float nomodelvertex3f[6*3] =
7140 static const float nomodelcolor4f[6*4] =
7142 0.0f, 0.0f, 0.5f, 1.0f,
7143 0.0f, 0.0f, 0.5f, 1.0f,
7144 0.0f, 0.5f, 0.0f, 1.0f,
7145 0.0f, 0.5f, 0.0f, 1.0f,
7146 0.5f, 0.0f, 0.0f, 1.0f,
7147 0.5f, 0.0f, 0.0f, 1.0f
7150 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7156 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);
7158 // this is only called once per entity so numsurfaces is always 1, and
7159 // surfacelist is always {0}, so this code does not handle batches
7161 if (rsurface.ent_flags & RENDER_ADDITIVE)
7163 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7164 GL_DepthMask(false);
7166 else if (rsurface.colormod[3] < 1)
7168 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7169 GL_DepthMask(false);
7173 GL_BlendFunc(GL_ONE, GL_ZERO);
7176 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7177 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7178 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7179 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7180 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7181 for (i = 0, c = color4f;i < 6;i++, c += 4)
7183 c[0] *= rsurface.colormod[0];
7184 c[1] *= rsurface.colormod[1];
7185 c[2] *= rsurface.colormod[2];
7186 c[3] *= rsurface.colormod[3];
7188 if (r_refdef.fogenabled)
7190 for (i = 0, c = color4f;i < 6;i++, c += 4)
7192 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7194 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7195 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7196 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7199 // R_Mesh_ResetTextureState();
7200 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7201 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7202 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7205 void R_DrawNoModel(entity_render_t *ent)
7208 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7209 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7210 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7212 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7215 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7217 vec3_t right1, right2, diff, normal;
7219 VectorSubtract (org2, org1, normal);
7221 // calculate 'right' vector for start
7222 VectorSubtract (r_refdef.view.origin, org1, diff);
7223 CrossProduct (normal, diff, right1);
7224 VectorNormalize (right1);
7226 // calculate 'right' vector for end
7227 VectorSubtract (r_refdef.view.origin, org2, diff);
7228 CrossProduct (normal, diff, right2);
7229 VectorNormalize (right2);
7231 vert[ 0] = org1[0] + width * right1[0];
7232 vert[ 1] = org1[1] + width * right1[1];
7233 vert[ 2] = org1[2] + width * right1[2];
7234 vert[ 3] = org1[0] - width * right1[0];
7235 vert[ 4] = org1[1] - width * right1[1];
7236 vert[ 5] = org1[2] - width * right1[2];
7237 vert[ 6] = org2[0] - width * right2[0];
7238 vert[ 7] = org2[1] - width * right2[1];
7239 vert[ 8] = org2[2] - width * right2[2];
7240 vert[ 9] = org2[0] + width * right2[0];
7241 vert[10] = org2[1] + width * right2[1];
7242 vert[11] = org2[2] + width * right2[2];
7245 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)
7247 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7248 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7249 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7250 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7251 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7252 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7253 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7254 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7255 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7256 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7257 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7258 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7261 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7266 VectorSet(v, x, y, z);
7267 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7268 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7270 if (i == mesh->numvertices)
7272 if (mesh->numvertices < mesh->maxvertices)
7274 VectorCopy(v, vertex3f);
7275 mesh->numvertices++;
7277 return mesh->numvertices;
7283 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7287 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7288 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7289 e = mesh->element3i + mesh->numtriangles * 3;
7290 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7292 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7293 if (mesh->numtriangles < mesh->maxtriangles)
7298 mesh->numtriangles++;
7300 element[1] = element[2];
7304 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7308 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7309 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7310 e = mesh->element3i + mesh->numtriangles * 3;
7311 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7313 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7314 if (mesh->numtriangles < mesh->maxtriangles)
7319 mesh->numtriangles++;
7321 element[1] = element[2];
7325 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7326 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7328 int planenum, planenum2;
7331 mplane_t *plane, *plane2;
7333 double temppoints[2][256*3];
7334 // figure out how large a bounding box we need to properly compute this brush
7336 for (w = 0;w < numplanes;w++)
7337 maxdist = max(maxdist, fabs(planes[w].dist));
7338 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7339 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7340 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7344 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7345 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7347 if (planenum2 == planenum)
7349 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);
7352 if (tempnumpoints < 3)
7354 // generate elements forming a triangle fan for this polygon
7355 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7359 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)
7361 texturelayer_t *layer;
7362 layer = t->currentlayers + t->currentnumlayers++;
7364 layer->depthmask = depthmask;
7365 layer->blendfunc1 = blendfunc1;
7366 layer->blendfunc2 = blendfunc2;
7367 layer->texture = texture;
7368 layer->texmatrix = *matrix;
7369 layer->color[0] = r;
7370 layer->color[1] = g;
7371 layer->color[2] = b;
7372 layer->color[3] = a;
7375 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7377 if(parms[0] == 0 && parms[1] == 0)
7379 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7380 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7385 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7388 index = parms[2] + rsurface.shadertime * parms[3];
7389 index -= floor(index);
7390 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7393 case Q3WAVEFUNC_NONE:
7394 case Q3WAVEFUNC_NOISE:
7395 case Q3WAVEFUNC_COUNT:
7398 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7399 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7400 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7401 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7402 case Q3WAVEFUNC_TRIANGLE:
7404 f = index - floor(index);
7415 f = parms[0] + parms[1] * f;
7416 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7417 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7421 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7427 matrix4x4_t matrix, temp;
7428 switch(tcmod->tcmod)
7432 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7433 matrix = r_waterscrollmatrix;
7435 matrix = identitymatrix;
7437 case Q3TCMOD_ENTITYTRANSLATE:
7438 // this is used in Q3 to allow the gamecode to control texcoord
7439 // scrolling on the entity, which is not supported in darkplaces yet.
7440 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7442 case Q3TCMOD_ROTATE:
7443 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7444 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
7445 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7448 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7450 case Q3TCMOD_SCROLL:
7451 // extra care is needed because of precision breakdown with large values of time
7452 offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7453 offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7454 Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7456 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7457 w = (int) tcmod->parms[0];
7458 h = (int) tcmod->parms[1];
7459 f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7461 idx = (int) floor(f * w * h);
7462 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7464 case Q3TCMOD_STRETCH:
7465 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7466 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7468 case Q3TCMOD_TRANSFORM:
7469 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
7470 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
7471 VectorSet(tcmat + 6, 0 , 0 , 1);
7472 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
7473 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7475 case Q3TCMOD_TURBULENT:
7476 // this is handled in the RSurf_PrepareVertices function
7477 matrix = identitymatrix;
7481 Matrix4x4_Concat(texmatrix, &matrix, &temp);
7484 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7486 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7487 char name[MAX_QPATH];
7488 skinframe_t *skinframe;
7489 unsigned char pixels[296*194];
7490 strlcpy(cache->name, skinname, sizeof(cache->name));
7491 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7492 if (developer_loading.integer)
7493 Con_Printf("loading %s\n", name);
7494 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7495 if (!skinframe || !skinframe->base)
7498 fs_offset_t filesize;
7500 f = FS_LoadFile(name, tempmempool, true, &filesize);
7503 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7504 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7508 cache->skinframe = skinframe;
7511 texture_t *R_GetCurrentTexture(texture_t *t)
7514 const entity_render_t *ent = rsurface.entity;
7515 dp_model_t *model = ent->model;
7516 q3shaderinfo_layer_tcmod_t *tcmod;
7518 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7519 return t->currentframe;
7520 t->update_lastrenderframe = r_textureframe;
7521 t->update_lastrenderentity = (void *)ent;
7523 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7524 t->camera_entity = ent->entitynumber;
7526 t->camera_entity = 0;
7528 // switch to an alternate material if this is a q1bsp animated material
7530 texture_t *texture = t;
7531 int s = rsurface.ent_skinnum;
7532 if ((unsigned int)s >= (unsigned int)model->numskins)
7534 if (model->skinscenes)
7536 if (model->skinscenes[s].framecount > 1)
7537 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7539 s = model->skinscenes[s].firstframe;
7542 t = t + s * model->num_surfaces;
7545 // use an alternate animation if the entity's frame is not 0,
7546 // and only if the texture has an alternate animation
7547 if (rsurface.ent_alttextures && t->anim_total[1])
7548 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7550 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7552 texture->currentframe = t;
7555 // update currentskinframe to be a qw skin or animation frame
7556 if (rsurface.ent_qwskin >= 0)
7558 i = rsurface.ent_qwskin;
7559 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7561 r_qwskincache_size = cl.maxclients;
7563 Mem_Free(r_qwskincache);
7564 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7566 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7567 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7568 t->currentskinframe = r_qwskincache[i].skinframe;
7569 if (t->currentskinframe == NULL)
7570 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7572 else if (t->numskinframes >= 2)
7573 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7574 if (t->backgroundnumskinframes >= 2)
7575 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7577 t->currentmaterialflags = t->basematerialflags;
7578 t->currentalpha = rsurface.colormod[3];
7579 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
7580 t->currentalpha *= r_wateralpha.value;
7581 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7582 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7583 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7584 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7585 if (!(rsurface.ent_flags & RENDER_LIGHT))
7586 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7587 else if (FAKELIGHT_ENABLED)
7589 // no modellight if using fakelight for the map
7591 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7593 // pick a model lighting mode
7594 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7595 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7597 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7599 if (rsurface.ent_flags & RENDER_ADDITIVE)
7600 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7601 else if (t->currentalpha < 1)
7602 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7603 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7604 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7605 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7606 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7607 if (t->backgroundnumskinframes)
7608 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7609 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7611 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7612 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7615 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7616 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7617 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7619 // there is no tcmod
7620 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7622 t->currenttexmatrix = r_waterscrollmatrix;
7623 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7625 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7627 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7628 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7631 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7632 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7633 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7634 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7636 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7637 if (t->currentskinframe->qpixels)
7638 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7639 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7640 if (!t->basetexture)
7641 t->basetexture = r_texture_notexture;
7642 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7643 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7644 t->nmaptexture = t->currentskinframe->nmap;
7645 if (!t->nmaptexture)
7646 t->nmaptexture = r_texture_blanknormalmap;
7647 t->glosstexture = r_texture_black;
7648 t->glowtexture = t->currentskinframe->glow;
7649 t->fogtexture = t->currentskinframe->fog;
7650 t->reflectmasktexture = t->currentskinframe->reflect;
7651 if (t->backgroundnumskinframes)
7653 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7654 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7655 t->backgroundglosstexture = r_texture_black;
7656 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7657 if (!t->backgroundnmaptexture)
7658 t->backgroundnmaptexture = r_texture_blanknormalmap;
7662 t->backgroundbasetexture = r_texture_white;
7663 t->backgroundnmaptexture = r_texture_blanknormalmap;
7664 t->backgroundglosstexture = r_texture_black;
7665 t->backgroundglowtexture = NULL;
7667 t->specularpower = r_shadow_glossexponent.value;
7668 // TODO: store reference values for these in the texture?
7669 t->specularscale = 0;
7670 if (r_shadow_gloss.integer > 0)
7672 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7674 if (r_shadow_glossintensity.value > 0)
7676 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7677 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7678 t->specularscale = r_shadow_glossintensity.value;
7681 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7683 t->glosstexture = r_texture_white;
7684 t->backgroundglosstexture = r_texture_white;
7685 t->specularscale = r_shadow_gloss2intensity.value;
7686 t->specularpower = r_shadow_gloss2exponent.value;
7689 t->specularscale *= t->specularscalemod;
7690 t->specularpower *= t->specularpowermod;
7692 // lightmaps mode looks bad with dlights using actual texturing, so turn
7693 // off the colormap and glossmap, but leave the normalmap on as it still
7694 // accurately represents the shading involved
7695 if (gl_lightmaps.integer)
7697 t->basetexture = r_texture_grey128;
7698 t->pantstexture = r_texture_black;
7699 t->shirttexture = r_texture_black;
7700 t->nmaptexture = r_texture_blanknormalmap;
7701 t->glosstexture = r_texture_black;
7702 t->glowtexture = NULL;
7703 t->fogtexture = NULL;
7704 t->reflectmasktexture = NULL;
7705 t->backgroundbasetexture = NULL;
7706 t->backgroundnmaptexture = r_texture_blanknormalmap;
7707 t->backgroundglosstexture = r_texture_black;
7708 t->backgroundglowtexture = NULL;
7709 t->specularscale = 0;
7710 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7713 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7714 VectorClear(t->dlightcolor);
7715 t->currentnumlayers = 0;
7716 if (t->currentmaterialflags & MATERIALFLAG_WALL)
7718 int blendfunc1, blendfunc2;
7720 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7722 blendfunc1 = GL_SRC_ALPHA;
7723 blendfunc2 = GL_ONE;
7725 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7727 blendfunc1 = GL_SRC_ALPHA;
7728 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7730 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7732 blendfunc1 = t->customblendfunc[0];
7733 blendfunc2 = t->customblendfunc[1];
7737 blendfunc1 = GL_ONE;
7738 blendfunc2 = GL_ZERO;
7740 // don't colormod evilblend textures
7741 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7742 VectorSet(t->lightmapcolor, 1, 1, 1);
7743 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7744 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7746 // fullbright is not affected by r_refdef.lightmapintensity
7747 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]);
7748 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7749 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]);
7750 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7751 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]);
7755 vec3_t ambientcolor;
7757 // set the color tint used for lights affecting this surface
7758 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7760 // q3bsp has no lightmap updates, so the lightstylevalue that
7761 // would normally be baked into the lightmap must be
7762 // applied to the color
7763 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7764 if (model->type == mod_brushq3)
7765 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7766 colorscale *= r_refdef.lightmapintensity;
7767 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7768 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7769 // basic lit geometry
7770 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]);
7771 // add pants/shirt if needed
7772 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7773 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]);
7774 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7775 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]);
7776 // now add ambient passes if needed
7777 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7779 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]);
7780 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7781 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]);
7782 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7783 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]);
7786 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7787 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]);
7788 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7790 // if this is opaque use alpha blend which will darken the earlier
7793 // if this is an alpha blended material, all the earlier passes
7794 // were darkened by fog already, so we only need to add the fog
7795 // color ontop through the fog mask texture
7797 // if this is an additive blended material, all the earlier passes
7798 // were darkened by fog already, and we should not add fog color
7799 // (because the background was not darkened, there is no fog color
7800 // that was lost behind it).
7801 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]);
7805 return t->currentframe;
7808 rsurfacestate_t rsurface;
7810 void RSurf_ActiveWorldEntity(void)
7812 dp_model_t *model = r_refdef.scene.worldmodel;
7813 //if (rsurface.entity == r_refdef.scene.worldentity)
7815 rsurface.entity = r_refdef.scene.worldentity;
7816 rsurface.skeleton = NULL;
7817 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7818 rsurface.ent_skinnum = 0;
7819 rsurface.ent_qwskin = -1;
7820 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7821 rsurface.shadertime = r_refdef.scene.time;
7822 rsurface.matrix = identitymatrix;
7823 rsurface.inversematrix = identitymatrix;
7824 rsurface.matrixscale = 1;
7825 rsurface.inversematrixscale = 1;
7826 R_EntityMatrix(&identitymatrix);
7827 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7828 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7829 rsurface.fograngerecip = r_refdef.fograngerecip;
7830 rsurface.fogheightfade = r_refdef.fogheightfade;
7831 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7832 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7833 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7834 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7835 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7836 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7837 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7838 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7839 rsurface.colormod[3] = 1;
7840 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);
7841 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7842 rsurface.frameblend[0].lerp = 1;
7843 rsurface.ent_alttextures = false;
7844 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7845 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7846 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7847 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7848 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7849 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7850 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7851 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7852 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7853 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7854 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7855 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7856 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7857 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7858 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7859 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7860 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7861 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7862 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7863 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7864 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7865 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7866 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7867 rsurface.modelelement3i = model->surfmesh.data_element3i;
7868 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7869 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7870 rsurface.modelelement3s = model->surfmesh.data_element3s;
7871 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7872 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7873 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7874 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7875 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7876 rsurface.modelsurfaces = model->data_surfaces;
7877 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7878 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7879 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7880 rsurface.modelgeneratedvertex = false;
7881 rsurface.batchgeneratedvertex = false;
7882 rsurface.batchfirstvertex = 0;
7883 rsurface.batchnumvertices = 0;
7884 rsurface.batchfirsttriangle = 0;
7885 rsurface.batchnumtriangles = 0;
7886 rsurface.batchvertex3f = NULL;
7887 rsurface.batchvertex3f_vertexbuffer = NULL;
7888 rsurface.batchvertex3f_bufferoffset = 0;
7889 rsurface.batchsvector3f = NULL;
7890 rsurface.batchsvector3f_vertexbuffer = NULL;
7891 rsurface.batchsvector3f_bufferoffset = 0;
7892 rsurface.batchtvector3f = NULL;
7893 rsurface.batchtvector3f_vertexbuffer = NULL;
7894 rsurface.batchtvector3f_bufferoffset = 0;
7895 rsurface.batchnormal3f = NULL;
7896 rsurface.batchnormal3f_vertexbuffer = NULL;
7897 rsurface.batchnormal3f_bufferoffset = 0;
7898 rsurface.batchlightmapcolor4f = NULL;
7899 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7900 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7901 rsurface.batchtexcoordtexture2f = NULL;
7902 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7903 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7904 rsurface.batchtexcoordlightmap2f = NULL;
7905 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7906 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7907 rsurface.batchvertexmesh = NULL;
7908 rsurface.batchvertexmeshbuffer = NULL;
7909 rsurface.batchvertex3fbuffer = NULL;
7910 rsurface.batchelement3i = NULL;
7911 rsurface.batchelement3i_indexbuffer = NULL;
7912 rsurface.batchelement3i_bufferoffset = 0;
7913 rsurface.batchelement3s = NULL;
7914 rsurface.batchelement3s_indexbuffer = NULL;
7915 rsurface.batchelement3s_bufferoffset = 0;
7916 rsurface.passcolor4f = NULL;
7917 rsurface.passcolor4f_vertexbuffer = NULL;
7918 rsurface.passcolor4f_bufferoffset = 0;
7921 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7923 dp_model_t *model = ent->model;
7924 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7926 rsurface.entity = (entity_render_t *)ent;
7927 rsurface.skeleton = ent->skeleton;
7928 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7929 rsurface.ent_skinnum = ent->skinnum;
7930 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;
7931 rsurface.ent_flags = ent->flags;
7932 rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
7933 rsurface.matrix = ent->matrix;
7934 rsurface.inversematrix = ent->inversematrix;
7935 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7936 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7937 R_EntityMatrix(&rsurface.matrix);
7938 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7939 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7940 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7941 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7942 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7943 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7944 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7945 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7946 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7947 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7948 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7949 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7950 rsurface.colormod[3] = ent->alpha;
7951 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7952 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7953 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7954 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7955 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7956 if (ent->model->brush.submodel && !prepass)
7958 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7959 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7961 if (model->surfmesh.isanimated && model->AnimateVertices)
7963 if (ent->animcache_vertex3f)
7965 rsurface.modelvertex3f = ent->animcache_vertex3f;
7966 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7967 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7968 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7969 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7970 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
7971 rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
7973 else if (wanttangents)
7975 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7976 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7977 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7978 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7979 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7980 rsurface.modelvertexmesh = NULL;
7981 rsurface.modelvertexmeshbuffer = NULL;
7982 rsurface.modelvertex3fbuffer = NULL;
7984 else if (wantnormals)
7986 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7987 rsurface.modelsvector3f = NULL;
7988 rsurface.modeltvector3f = NULL;
7989 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7990 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
7991 rsurface.modelvertexmesh = NULL;
7992 rsurface.modelvertexmeshbuffer = NULL;
7993 rsurface.modelvertex3fbuffer = NULL;
7997 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7998 rsurface.modelsvector3f = NULL;
7999 rsurface.modeltvector3f = NULL;
8000 rsurface.modelnormal3f = NULL;
8001 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8002 rsurface.modelvertexmesh = NULL;
8003 rsurface.modelvertexmeshbuffer = NULL;
8004 rsurface.modelvertex3fbuffer = NULL;
8006 rsurface.modelvertex3f_vertexbuffer = 0;
8007 rsurface.modelvertex3f_bufferoffset = 0;
8008 rsurface.modelsvector3f_vertexbuffer = 0;
8009 rsurface.modelsvector3f_bufferoffset = 0;
8010 rsurface.modeltvector3f_vertexbuffer = 0;
8011 rsurface.modeltvector3f_bufferoffset = 0;
8012 rsurface.modelnormal3f_vertexbuffer = 0;
8013 rsurface.modelnormal3f_bufferoffset = 0;
8014 rsurface.modelgeneratedvertex = true;
8018 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8019 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8020 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8021 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8022 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8023 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8024 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8025 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8026 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8027 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8028 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8029 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8030 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8031 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8032 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8033 rsurface.modelgeneratedvertex = false;
8035 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8036 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8037 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8038 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8039 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8040 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8041 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8042 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8043 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8044 rsurface.modelelement3i = model->surfmesh.data_element3i;
8045 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8046 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8047 rsurface.modelelement3s = model->surfmesh.data_element3s;
8048 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8049 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8050 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8051 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8052 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8053 rsurface.modelsurfaces = model->data_surfaces;
8054 rsurface.batchgeneratedvertex = false;
8055 rsurface.batchfirstvertex = 0;
8056 rsurface.batchnumvertices = 0;
8057 rsurface.batchfirsttriangle = 0;
8058 rsurface.batchnumtriangles = 0;
8059 rsurface.batchvertex3f = NULL;
8060 rsurface.batchvertex3f_vertexbuffer = NULL;
8061 rsurface.batchvertex3f_bufferoffset = 0;
8062 rsurface.batchsvector3f = NULL;
8063 rsurface.batchsvector3f_vertexbuffer = NULL;
8064 rsurface.batchsvector3f_bufferoffset = 0;
8065 rsurface.batchtvector3f = NULL;
8066 rsurface.batchtvector3f_vertexbuffer = NULL;
8067 rsurface.batchtvector3f_bufferoffset = 0;
8068 rsurface.batchnormal3f = NULL;
8069 rsurface.batchnormal3f_vertexbuffer = NULL;
8070 rsurface.batchnormal3f_bufferoffset = 0;
8071 rsurface.batchlightmapcolor4f = NULL;
8072 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8073 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8074 rsurface.batchtexcoordtexture2f = NULL;
8075 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8076 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8077 rsurface.batchtexcoordlightmap2f = NULL;
8078 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8079 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8080 rsurface.batchvertexmesh = NULL;
8081 rsurface.batchvertexmeshbuffer = NULL;
8082 rsurface.batchvertex3fbuffer = NULL;
8083 rsurface.batchelement3i = NULL;
8084 rsurface.batchelement3i_indexbuffer = NULL;
8085 rsurface.batchelement3i_bufferoffset = 0;
8086 rsurface.batchelement3s = NULL;
8087 rsurface.batchelement3s_indexbuffer = NULL;
8088 rsurface.batchelement3s_bufferoffset = 0;
8089 rsurface.passcolor4f = NULL;
8090 rsurface.passcolor4f_vertexbuffer = NULL;
8091 rsurface.passcolor4f_bufferoffset = 0;
8094 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)
8096 rsurface.entity = r_refdef.scene.worldentity;
8097 rsurface.skeleton = NULL;
8098 rsurface.ent_skinnum = 0;
8099 rsurface.ent_qwskin = -1;
8100 rsurface.ent_flags = entflags;
8101 rsurface.shadertime = r_refdef.scene.time - shadertime;
8102 rsurface.modelnumvertices = numvertices;
8103 rsurface.modelnumtriangles = numtriangles;
8104 rsurface.matrix = *matrix;
8105 rsurface.inversematrix = *inversematrix;
8106 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8107 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8108 R_EntityMatrix(&rsurface.matrix);
8109 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8110 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8111 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8112 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8113 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8114 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8115 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8116 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8117 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8118 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8119 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8120 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8121 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);
8122 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8123 rsurface.frameblend[0].lerp = 1;
8124 rsurface.ent_alttextures = false;
8125 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8126 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8129 rsurface.modelvertex3f = (float *)vertex3f;
8130 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8131 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8132 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8134 else if (wantnormals)
8136 rsurface.modelvertex3f = (float *)vertex3f;
8137 rsurface.modelsvector3f = NULL;
8138 rsurface.modeltvector3f = NULL;
8139 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8143 rsurface.modelvertex3f = (float *)vertex3f;
8144 rsurface.modelsvector3f = NULL;
8145 rsurface.modeltvector3f = NULL;
8146 rsurface.modelnormal3f = NULL;
8148 rsurface.modelvertexmesh = NULL;
8149 rsurface.modelvertexmeshbuffer = NULL;
8150 rsurface.modelvertex3fbuffer = NULL;
8151 rsurface.modelvertex3f_vertexbuffer = 0;
8152 rsurface.modelvertex3f_bufferoffset = 0;
8153 rsurface.modelsvector3f_vertexbuffer = 0;
8154 rsurface.modelsvector3f_bufferoffset = 0;
8155 rsurface.modeltvector3f_vertexbuffer = 0;
8156 rsurface.modeltvector3f_bufferoffset = 0;
8157 rsurface.modelnormal3f_vertexbuffer = 0;
8158 rsurface.modelnormal3f_bufferoffset = 0;
8159 rsurface.modelgeneratedvertex = true;
8160 rsurface.modellightmapcolor4f = (float *)color4f;
8161 rsurface.modellightmapcolor4f_vertexbuffer = 0;
8162 rsurface.modellightmapcolor4f_bufferoffset = 0;
8163 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
8164 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8165 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8166 rsurface.modeltexcoordlightmap2f = NULL;
8167 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8168 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8169 rsurface.modelelement3i = (int *)element3i;
8170 rsurface.modelelement3i_indexbuffer = NULL;
8171 rsurface.modelelement3i_bufferoffset = 0;
8172 rsurface.modelelement3s = (unsigned short *)element3s;
8173 rsurface.modelelement3s_indexbuffer = NULL;
8174 rsurface.modelelement3s_bufferoffset = 0;
8175 rsurface.modellightmapoffsets = NULL;
8176 rsurface.modelsurfaces = NULL;
8177 rsurface.batchgeneratedvertex = false;
8178 rsurface.batchfirstvertex = 0;
8179 rsurface.batchnumvertices = 0;
8180 rsurface.batchfirsttriangle = 0;
8181 rsurface.batchnumtriangles = 0;
8182 rsurface.batchvertex3f = NULL;
8183 rsurface.batchvertex3f_vertexbuffer = NULL;
8184 rsurface.batchvertex3f_bufferoffset = 0;
8185 rsurface.batchsvector3f = NULL;
8186 rsurface.batchsvector3f_vertexbuffer = NULL;
8187 rsurface.batchsvector3f_bufferoffset = 0;
8188 rsurface.batchtvector3f = NULL;
8189 rsurface.batchtvector3f_vertexbuffer = NULL;
8190 rsurface.batchtvector3f_bufferoffset = 0;
8191 rsurface.batchnormal3f = NULL;
8192 rsurface.batchnormal3f_vertexbuffer = NULL;
8193 rsurface.batchnormal3f_bufferoffset = 0;
8194 rsurface.batchlightmapcolor4f = NULL;
8195 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8196 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8197 rsurface.batchtexcoordtexture2f = NULL;
8198 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8199 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8200 rsurface.batchtexcoordlightmap2f = NULL;
8201 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8202 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8203 rsurface.batchvertexmesh = NULL;
8204 rsurface.batchvertexmeshbuffer = NULL;
8205 rsurface.batchvertex3fbuffer = NULL;
8206 rsurface.batchelement3i = NULL;
8207 rsurface.batchelement3i_indexbuffer = NULL;
8208 rsurface.batchelement3i_bufferoffset = 0;
8209 rsurface.batchelement3s = NULL;
8210 rsurface.batchelement3s_indexbuffer = NULL;
8211 rsurface.batchelement3s_bufferoffset = 0;
8212 rsurface.passcolor4f = NULL;
8213 rsurface.passcolor4f_vertexbuffer = NULL;
8214 rsurface.passcolor4f_bufferoffset = 0;
8216 if (rsurface.modelnumvertices && rsurface.modelelement3i)
8218 if ((wantnormals || wanttangents) && !normal3f)
8220 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8221 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8223 if (wanttangents && !svector3f)
8225 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8226 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8227 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8232 float RSurf_FogPoint(const float *v)
8234 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8235 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8236 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8237 float FogHeightFade = r_refdef.fogheightfade;
8239 unsigned int fogmasktableindex;
8240 if (r_refdef.fogplaneviewabove)
8241 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8243 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8244 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8245 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8248 float RSurf_FogVertex(const float *v)
8250 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8251 float FogPlaneViewDist = rsurface.fogplaneviewdist;
8252 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8253 float FogHeightFade = rsurface.fogheightfade;
8255 unsigned int fogmasktableindex;
8256 if (r_refdef.fogplaneviewabove)
8257 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8259 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8260 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8261 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8264 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8267 for (i = 0;i < numelements;i++)
8268 outelement3i[i] = inelement3i[i] + adjust;
8271 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8272 extern cvar_t gl_vbo;
8273 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8281 int surfacefirsttriangle;
8282 int surfacenumtriangles;
8283 int surfacefirstvertex;
8284 int surfaceendvertex;
8285 int surfacenumvertices;
8286 int batchnumvertices;
8287 int batchnumtriangles;
8291 qboolean dynamicvertex;
8295 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8297 q3shaderinfo_deform_t *deform;
8298 const msurface_t *surface, *firstsurface;
8299 r_vertexmesh_t *vertexmesh;
8300 if (!texturenumsurfaces)
8302 // find vertex range of this surface batch
8304 firstsurface = texturesurfacelist[0];
8305 firsttriangle = firstsurface->num_firsttriangle;
8306 batchnumvertices = 0;
8307 batchnumtriangles = 0;
8308 firstvertex = endvertex = firstsurface->num_firstvertex;
8309 for (i = 0;i < texturenumsurfaces;i++)
8311 surface = texturesurfacelist[i];
8312 if (surface != firstsurface + i)
8314 surfacefirstvertex = surface->num_firstvertex;
8315 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8316 surfacenumvertices = surface->num_vertices;
8317 surfacenumtriangles = surface->num_triangles;
8318 if (firstvertex > surfacefirstvertex)
8319 firstvertex = surfacefirstvertex;
8320 if (endvertex < surfaceendvertex)
8321 endvertex = surfaceendvertex;
8322 batchnumvertices += surfacenumvertices;
8323 batchnumtriangles += surfacenumtriangles;
8326 // we now know the vertex range used, and if there are any gaps in it
8327 rsurface.batchfirstvertex = firstvertex;
8328 rsurface.batchnumvertices = endvertex - firstvertex;
8329 rsurface.batchfirsttriangle = firsttriangle;
8330 rsurface.batchnumtriangles = batchnumtriangles;
8332 // this variable holds flags for which properties have been updated that
8333 // may require regenerating vertexmesh array...
8336 // check if any dynamic vertex processing must occur
8337 dynamicvertex = false;
8339 // if there is a chance of animated vertex colors, it's a dynamic batch
8340 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8342 dynamicvertex = true;
8343 batchneed |= BATCHNEED_NOGAPS;
8344 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8347 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8349 switch (deform->deform)
8352 case Q3DEFORM_PROJECTIONSHADOW:
8353 case Q3DEFORM_TEXT0:
8354 case Q3DEFORM_TEXT1:
8355 case Q3DEFORM_TEXT2:
8356 case Q3DEFORM_TEXT3:
8357 case Q3DEFORM_TEXT4:
8358 case Q3DEFORM_TEXT5:
8359 case Q3DEFORM_TEXT6:
8360 case Q3DEFORM_TEXT7:
8363 case Q3DEFORM_AUTOSPRITE:
8364 dynamicvertex = true;
8365 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8366 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8368 case Q3DEFORM_AUTOSPRITE2:
8369 dynamicvertex = true;
8370 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8371 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8373 case Q3DEFORM_NORMAL:
8374 dynamicvertex = true;
8375 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8376 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8379 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8380 break; // if wavefunc is a nop, ignore this transform
8381 dynamicvertex = true;
8382 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8383 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8385 case Q3DEFORM_BULGE:
8386 dynamicvertex = true;
8387 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8388 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8391 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8392 break; // if wavefunc is a nop, ignore this transform
8393 dynamicvertex = true;
8394 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8395 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8399 switch(rsurface.texture->tcgen.tcgen)
8402 case Q3TCGEN_TEXTURE:
8404 case Q3TCGEN_LIGHTMAP:
8405 dynamicvertex = true;
8406 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8407 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8409 case Q3TCGEN_VECTOR:
8410 dynamicvertex = true;
8411 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8412 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8414 case Q3TCGEN_ENVIRONMENT:
8415 dynamicvertex = true;
8416 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8417 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8420 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8422 dynamicvertex = true;
8423 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8424 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8427 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8429 dynamicvertex = true;
8430 batchneed |= BATCHNEED_NOGAPS;
8431 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8434 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8436 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8437 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
8438 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
8439 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
8440 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8441 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8442 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8445 // when the model data has no vertex buffer (dynamic mesh), we need to
8447 if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8448 batchneed |= BATCHNEED_NOGAPS;
8450 // if needsupdate, we have to do a dynamic vertex batch for sure
8451 if (needsupdate & batchneed)
8452 dynamicvertex = true;
8454 // see if we need to build vertexmesh from arrays
8455 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8456 dynamicvertex = true;
8458 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8459 // also some drivers strongly dislike firstvertex
8460 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8461 dynamicvertex = true;
8463 rsurface.batchvertex3f = rsurface.modelvertex3f;
8464 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8465 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8466 rsurface.batchsvector3f = rsurface.modelsvector3f;
8467 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8468 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8469 rsurface.batchtvector3f = rsurface.modeltvector3f;
8470 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8471 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8472 rsurface.batchnormal3f = rsurface.modelnormal3f;
8473 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8474 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8475 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8476 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
8477 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8478 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8479 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
8480 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
8481 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8482 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8483 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8484 rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8485 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8486 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8487 rsurface.batchelement3i = rsurface.modelelement3i;
8488 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8489 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8490 rsurface.batchelement3s = rsurface.modelelement3s;
8491 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8492 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8494 // if any dynamic vertex processing has to occur in software, we copy the
8495 // entire surface list together before processing to rebase the vertices
8496 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8498 // if any gaps exist and we do not have a static vertex buffer, we have to
8499 // copy the surface list together to avoid wasting upload bandwidth on the
8500 // vertices in the gaps.
8502 // if gaps exist and we have a static vertex buffer, we still have to
8503 // combine the index buffer ranges into one dynamic index buffer.
8505 // in all cases we end up with data that can be drawn in one call.
8509 // static vertex data, just set pointers...
8510 rsurface.batchgeneratedvertex = false;
8511 // if there are gaps, we want to build a combined index buffer,
8512 // otherwise use the original static buffer with an appropriate offset
8515 // build a new triangle elements array for this batch
8516 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8517 rsurface.batchfirsttriangle = 0;
8519 for (i = 0;i < texturenumsurfaces;i++)
8521 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8522 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8523 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8524 numtriangles += surfacenumtriangles;
8526 rsurface.batchelement3i_indexbuffer = NULL;
8527 rsurface.batchelement3i_bufferoffset = 0;
8528 rsurface.batchelement3s = NULL;
8529 rsurface.batchelement3s_indexbuffer = NULL;
8530 rsurface.batchelement3s_bufferoffset = 0;
8531 if (endvertex <= 65536)
8533 // make a 16bit (unsigned short) index array if possible
8534 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8535 for (i = 0;i < numtriangles*3;i++)
8536 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8542 // something needs software processing, do it for real...
8543 // we only directly handle separate array data in this case and then
8544 // generate interleaved data if needed...
8545 rsurface.batchgeneratedvertex = true;
8547 // now copy the vertex data into a combined array and make an index array
8548 // (this is what Quake3 does all the time)
8549 //if (gaps || rsurface.batchfirstvertex)
8551 rsurface.batchvertex3fbuffer = NULL;
8552 rsurface.batchvertexmesh = NULL;
8553 rsurface.batchvertexmeshbuffer = NULL;
8554 rsurface.batchvertex3f = NULL;
8555 rsurface.batchvertex3f_vertexbuffer = NULL;
8556 rsurface.batchvertex3f_bufferoffset = 0;
8557 rsurface.batchsvector3f = NULL;
8558 rsurface.batchsvector3f_vertexbuffer = NULL;
8559 rsurface.batchsvector3f_bufferoffset = 0;
8560 rsurface.batchtvector3f = NULL;
8561 rsurface.batchtvector3f_vertexbuffer = NULL;
8562 rsurface.batchtvector3f_bufferoffset = 0;
8563 rsurface.batchnormal3f = NULL;
8564 rsurface.batchnormal3f_vertexbuffer = NULL;
8565 rsurface.batchnormal3f_bufferoffset = 0;
8566 rsurface.batchlightmapcolor4f = NULL;
8567 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8568 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8569 rsurface.batchtexcoordtexture2f = NULL;
8570 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8571 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8572 rsurface.batchtexcoordlightmap2f = NULL;
8573 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8574 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8575 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8576 rsurface.batchelement3i_indexbuffer = NULL;
8577 rsurface.batchelement3i_bufferoffset = 0;
8578 rsurface.batchelement3s = NULL;
8579 rsurface.batchelement3s_indexbuffer = NULL;
8580 rsurface.batchelement3s_bufferoffset = 0;
8581 // we'll only be setting up certain arrays as needed
8582 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8583 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8584 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8585 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8586 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8587 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8588 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8590 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8591 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8593 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8594 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8595 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8596 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8597 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8598 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8601 for (i = 0;i < texturenumsurfaces;i++)
8603 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8604 surfacenumvertices = texturesurfacelist[i]->num_vertices;
8605 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8606 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8607 // copy only the data requested
8608 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8609 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8610 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8612 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8614 if (rsurface.batchvertex3f)
8615 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8617 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8619 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8621 if (rsurface.modelnormal3f)
8622 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8624 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8626 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8628 if (rsurface.modelsvector3f)
8630 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8631 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8635 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8636 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8639 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8641 if (rsurface.modellightmapcolor4f)
8642 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8644 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
8646 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8648 if (rsurface.modeltexcoordtexture2f)
8649 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8651 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8653 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8655 if (rsurface.modeltexcoordlightmap2f)
8656 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8658 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8661 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8662 numvertices += surfacenumvertices;
8663 numtriangles += surfacenumtriangles;
8666 // generate a 16bit index array as well if possible
8667 // (in general, dynamic batches fit)
8668 if (numvertices <= 65536)
8670 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8671 for (i = 0;i < numtriangles*3;i++)
8672 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8675 // since we've copied everything, the batch now starts at 0
8676 rsurface.batchfirstvertex = 0;
8677 rsurface.batchnumvertices = batchnumvertices;
8678 rsurface.batchfirsttriangle = 0;
8679 rsurface.batchnumtriangles = batchnumtriangles;
8682 // q1bsp surfaces rendered in vertex color mode have to have colors
8683 // calculated based on lightstyles
8684 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8686 // generate color arrays for the surfaces in this list
8691 const unsigned char *lm;
8692 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8693 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8694 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8696 for (i = 0;i < texturenumsurfaces;i++)
8698 surface = texturesurfacelist[i];
8699 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8700 surfacenumvertices = surface->num_vertices;
8701 if (surface->lightmapinfo->samples)
8703 for (j = 0;j < surfacenumvertices;j++)
8705 lm = surface->lightmapinfo->samples + offsets[j];
8706 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8707 VectorScale(lm, scale, c);
8708 if (surface->lightmapinfo->styles[1] != 255)
8710 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8712 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8713 VectorMA(c, scale, lm, c);
8714 if (surface->lightmapinfo->styles[2] != 255)
8717 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8718 VectorMA(c, scale, lm, c);
8719 if (surface->lightmapinfo->styles[3] != 255)
8722 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8723 VectorMA(c, scale, lm, c);
8730 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);
8736 for (j = 0;j < surfacenumvertices;j++)
8738 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8745 // if vertices are deformed (sprite flares and things in maps, possibly
8746 // water waves, bulges and other deformations), modify the copied vertices
8748 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8750 switch (deform->deform)
8753 case Q3DEFORM_PROJECTIONSHADOW:
8754 case Q3DEFORM_TEXT0:
8755 case Q3DEFORM_TEXT1:
8756 case Q3DEFORM_TEXT2:
8757 case Q3DEFORM_TEXT3:
8758 case Q3DEFORM_TEXT4:
8759 case Q3DEFORM_TEXT5:
8760 case Q3DEFORM_TEXT6:
8761 case Q3DEFORM_TEXT7:
8764 case Q3DEFORM_AUTOSPRITE:
8765 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8766 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8767 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8768 VectorNormalize(newforward);
8769 VectorNormalize(newright);
8770 VectorNormalize(newup);
8771 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8772 // rsurface.batchvertex3f_vertexbuffer = NULL;
8773 // rsurface.batchvertex3f_bufferoffset = 0;
8774 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8775 // rsurface.batchsvector3f_vertexbuffer = NULL;
8776 // rsurface.batchsvector3f_bufferoffset = 0;
8777 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8778 // rsurface.batchtvector3f_vertexbuffer = NULL;
8779 // rsurface.batchtvector3f_bufferoffset = 0;
8780 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8781 // rsurface.batchnormal3f_vertexbuffer = NULL;
8782 // rsurface.batchnormal3f_bufferoffset = 0;
8783 // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
8784 if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
8785 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8786 if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
8787 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);
8788 // a single autosprite surface can contain multiple sprites...
8789 for (j = 0;j < batchnumvertices - 3;j += 4)
8791 VectorClear(center);
8792 for (i = 0;i < 4;i++)
8793 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8794 VectorScale(center, 0.25f, center);
8795 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8796 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8797 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8798 for (i = 0;i < 4;i++)
8800 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8801 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8804 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8805 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8806 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);
8808 case Q3DEFORM_AUTOSPRITE2:
8809 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8810 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8811 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8812 VectorNormalize(newforward);
8813 VectorNormalize(newright);
8814 VectorNormalize(newup);
8815 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8816 // rsurface.batchvertex3f_vertexbuffer = NULL;
8817 // rsurface.batchvertex3f_bufferoffset = 0;
8819 const float *v1, *v2;
8829 memset(shortest, 0, sizeof(shortest));
8830 // a single autosprite surface can contain multiple sprites...
8831 for (j = 0;j < batchnumvertices - 3;j += 4)
8833 VectorClear(center);
8834 for (i = 0;i < 4;i++)
8835 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8836 VectorScale(center, 0.25f, center);
8837 // find the two shortest edges, then use them to define the
8838 // axis vectors for rotating around the central axis
8839 for (i = 0;i < 6;i++)
8841 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8842 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8843 l = VectorDistance2(v1, v2);
8844 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8846 l += (1.0f / 1024.0f);
8847 if (shortest[0].length2 > l || i == 0)
8849 shortest[1] = shortest[0];
8850 shortest[0].length2 = l;
8851 shortest[0].v1 = v1;
8852 shortest[0].v2 = v2;
8854 else if (shortest[1].length2 > l || i == 1)
8856 shortest[1].length2 = l;
8857 shortest[1].v1 = v1;
8858 shortest[1].v2 = v2;
8861 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8862 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8863 // this calculates the right vector from the shortest edge
8864 // and the up vector from the edge midpoints
8865 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8866 VectorNormalize(right);
8867 VectorSubtract(end, start, up);
8868 VectorNormalize(up);
8869 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8870 VectorSubtract(rsurface.localvieworigin, center, forward);
8871 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8872 VectorNegate(forward, forward);
8873 VectorReflect(forward, 0, up, forward);
8874 VectorNormalize(forward);
8875 CrossProduct(up, forward, newright);
8876 VectorNormalize(newright);
8877 // rotate the quad around the up axis vector, this is made
8878 // especially easy by the fact we know the quad is flat,
8879 // so we only have to subtract the center position and
8880 // measure distance along the right vector, and then
8881 // multiply that by the newright vector and add back the
8883 // we also need to subtract the old position to undo the
8884 // displacement from the center, which we do with a
8885 // DotProduct, the subtraction/addition of center is also
8886 // optimized into DotProducts here
8887 l = DotProduct(right, center);
8888 for (i = 0;i < 4;i++)
8890 v1 = rsurface.batchvertex3f + 3*(j+i);
8891 f = DotProduct(right, v1) - l;
8892 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8896 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8898 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8899 // rsurface.batchnormal3f_vertexbuffer = NULL;
8900 // rsurface.batchnormal3f_bufferoffset = 0;
8901 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8903 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8905 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8906 // rsurface.batchsvector3f_vertexbuffer = NULL;
8907 // rsurface.batchsvector3f_bufferoffset = 0;
8908 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8909 // rsurface.batchtvector3f_vertexbuffer = NULL;
8910 // rsurface.batchtvector3f_bufferoffset = 0;
8911 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);
8914 case Q3DEFORM_NORMAL:
8915 // deform the normals to make reflections wavey
8916 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8917 rsurface.batchnormal3f_vertexbuffer = NULL;
8918 rsurface.batchnormal3f_bufferoffset = 0;
8919 for (j = 0;j < batchnumvertices;j++)
8922 float *normal = rsurface.batchnormal3f + 3*j;
8923 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8924 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
8925 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
8926 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
8927 VectorNormalize(normal);
8929 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8931 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8932 // rsurface.batchsvector3f_vertexbuffer = NULL;
8933 // rsurface.batchsvector3f_bufferoffset = 0;
8934 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8935 // rsurface.batchtvector3f_vertexbuffer = NULL;
8936 // rsurface.batchtvector3f_bufferoffset = 0;
8937 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);
8941 // deform vertex array to make wavey water and flags and such
8942 waveparms[0] = deform->waveparms[0];
8943 waveparms[1] = deform->waveparms[1];
8944 waveparms[2] = deform->waveparms[2];
8945 waveparms[3] = deform->waveparms[3];
8946 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8947 break; // if wavefunc is a nop, don't make a dynamic vertex array
8948 // this is how a divisor of vertex influence on deformation
8949 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8950 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8951 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8952 // rsurface.batchvertex3f_vertexbuffer = NULL;
8953 // rsurface.batchvertex3f_bufferoffset = 0;
8954 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8955 // rsurface.batchnormal3f_vertexbuffer = NULL;
8956 // rsurface.batchnormal3f_bufferoffset = 0;
8957 for (j = 0;j < batchnumvertices;j++)
8959 // if the wavefunc depends on time, evaluate it per-vertex
8962 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8963 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8965 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8967 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8968 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8969 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8971 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8972 // rsurface.batchsvector3f_vertexbuffer = NULL;
8973 // rsurface.batchsvector3f_bufferoffset = 0;
8974 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8975 // rsurface.batchtvector3f_vertexbuffer = NULL;
8976 // rsurface.batchtvector3f_bufferoffset = 0;
8977 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
8980 case Q3DEFORM_BULGE:
8981 // deform vertex array to make the surface have moving bulges
8982 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8983 // rsurface.batchvertex3f_vertexbuffer = NULL;
8984 // rsurface.batchvertex3f_bufferoffset = 0;
8985 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8986 // rsurface.batchnormal3f_vertexbuffer = NULL;
8987 // rsurface.batchnormal3f_bufferoffset = 0;
8988 for (j = 0;j < batchnumvertices;j++)
8990 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
8991 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8993 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8994 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8995 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8997 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8998 // rsurface.batchsvector3f_vertexbuffer = NULL;
8999 // rsurface.batchsvector3f_bufferoffset = 0;
9000 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9001 // rsurface.batchtvector3f_vertexbuffer = NULL;
9002 // rsurface.batchtvector3f_bufferoffset = 0;
9003 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
9007 // deform vertex array
9008 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9009 break; // if wavefunc is a nop, don't make a dynamic vertex array
9010 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9011 VectorScale(deform->parms, scale, waveparms);
9012 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9013 // rsurface.batchvertex3f_vertexbuffer = NULL;
9014 // rsurface.batchvertex3f_bufferoffset = 0;
9015 for (j = 0;j < batchnumvertices;j++)
9016 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9021 // generate texcoords based on the chosen texcoord source
9022 switch(rsurface.texture->tcgen.tcgen)
9025 case Q3TCGEN_TEXTURE:
9027 case Q3TCGEN_LIGHTMAP:
9028 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9029 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9030 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9031 if (rsurface.batchtexcoordlightmap2f)
9032 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9034 case Q3TCGEN_VECTOR:
9035 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9036 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9037 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9038 for (j = 0;j < batchnumvertices;j++)
9040 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9041 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9044 case Q3TCGEN_ENVIRONMENT:
9045 // make environment reflections using a spheremap
9046 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9047 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9048 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9049 for (j = 0;j < batchnumvertices;j++)
9051 // identical to Q3A's method, but executed in worldspace so
9052 // carried models can be shiny too
9054 float viewer[3], d, reflected[3], worldreflected[3];
9056 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9057 // VectorNormalize(viewer);
9059 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9061 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9062 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9063 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9064 // note: this is proportinal to viewer, so we can normalize later
9066 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9067 VectorNormalize(worldreflected);
9069 // note: this sphere map only uses world x and z!
9070 // so positive and negative y will LOOK THE SAME.
9071 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9072 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9076 // the only tcmod that needs software vertex processing is turbulent, so
9077 // check for it here and apply the changes if needed
9078 // and we only support that as the first one
9079 // (handling a mixture of turbulent and other tcmods would be problematic
9080 // without punting it entirely to a software path)
9081 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9083 amplitude = rsurface.texture->tcmods[0].parms[1];
9084 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9085 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9086 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9087 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9088 for (j = 0;j < batchnumvertices;j++)
9090 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);
9091 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9095 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9097 // convert the modified arrays to vertex structs
9098 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9099 // rsurface.batchvertexmeshbuffer = NULL;
9100 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9101 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9102 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9103 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9104 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9105 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9106 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9108 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9110 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9111 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9114 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9115 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9116 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9117 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9118 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9119 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9120 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9121 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9122 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9126 void RSurf_DrawBatch(void)
9128 // sometimes a zero triangle surface (usually a degenerate patch) makes it
9129 // through the pipeline, killing it earlier in the pipeline would have
9130 // per-surface overhead rather than per-batch overhead, so it's best to
9131 // reject it here, before it hits glDraw.
9132 if (rsurface.batchnumtriangles == 0)
9135 // batch debugging code
9136 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9142 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9143 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9146 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9148 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9150 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9151 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);
9158 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);
9161 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9163 // pick the closest matching water plane
9164 int planeindex, vertexindex, bestplaneindex = -1;
9168 r_waterstate_waterplane_t *p;
9169 qboolean prepared = false;
9171 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9173 if(p->camera_entity != rsurface.texture->camera_entity)
9178 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9180 if(rsurface.batchnumvertices == 0)
9183 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9185 Matrix4x4_Transform(&rsurface.matrix, v, vert);
9186 d += fabs(PlaneDiff(vert, &p->plane));
9188 if (bestd > d || bestplaneindex < 0)
9191 bestplaneindex = planeindex;
9194 return bestplaneindex;
9195 // NOTE: this MAY return a totally unrelated water plane; we can ignore
9196 // this situation though, as it might be better to render single larger
9197 // batches with useless stuff (backface culled for example) than to
9198 // render multiple smaller batches
9201 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9204 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9205 rsurface.passcolor4f_vertexbuffer = 0;
9206 rsurface.passcolor4f_bufferoffset = 0;
9207 for (i = 0;i < rsurface.batchnumvertices;i++)
9208 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9211 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9218 if (rsurface.passcolor4f)
9220 // generate color arrays
9221 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9222 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9223 rsurface.passcolor4f_vertexbuffer = 0;
9224 rsurface.passcolor4f_bufferoffset = 0;
9225 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)
9227 f = RSurf_FogVertex(v);
9236 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9237 rsurface.passcolor4f_vertexbuffer = 0;
9238 rsurface.passcolor4f_bufferoffset = 0;
9239 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9241 f = RSurf_FogVertex(v);
9250 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9257 if (!rsurface.passcolor4f)
9259 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9260 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9261 rsurface.passcolor4f_vertexbuffer = 0;
9262 rsurface.passcolor4f_bufferoffset = 0;
9263 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)
9265 f = RSurf_FogVertex(v);
9266 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9267 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9268 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9273 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9278 if (!rsurface.passcolor4f)
9280 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9281 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9282 rsurface.passcolor4f_vertexbuffer = 0;
9283 rsurface.passcolor4f_bufferoffset = 0;
9284 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9293 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9298 if (!rsurface.passcolor4f)
9300 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9301 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9302 rsurface.passcolor4f_vertexbuffer = 0;
9303 rsurface.passcolor4f_bufferoffset = 0;
9304 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9306 c2[0] = c[0] + r_refdef.scene.ambient;
9307 c2[1] = c[1] + r_refdef.scene.ambient;
9308 c2[2] = c[2] + r_refdef.scene.ambient;
9313 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9316 rsurface.passcolor4f = NULL;
9317 rsurface.passcolor4f_vertexbuffer = 0;
9318 rsurface.passcolor4f_bufferoffset = 0;
9319 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9320 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9321 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9322 GL_Color(r, g, b, a);
9323 R_Mesh_TexBind(0, rsurface.lightmaptexture);
9327 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9329 // TODO: optimize applyfog && applycolor case
9330 // just apply fog if necessary, and tint the fog color array if necessary
9331 rsurface.passcolor4f = NULL;
9332 rsurface.passcolor4f_vertexbuffer = 0;
9333 rsurface.passcolor4f_bufferoffset = 0;
9334 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9335 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9336 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9337 GL_Color(r, g, b, a);
9341 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9344 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9345 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9346 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9347 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9348 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9349 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9350 GL_Color(r, g, b, a);
9354 static void RSurf_DrawBatch_GL11_ClampColor(void)
9359 if (!rsurface.passcolor4f)
9361 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9363 c2[0] = bound(0.0f, c1[0], 1.0f);
9364 c2[1] = bound(0.0f, c1[1], 1.0f);
9365 c2[2] = bound(0.0f, c1[2], 1.0f);
9366 c2[3] = bound(0.0f, c1[3], 1.0f);
9370 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9380 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9381 rsurface.passcolor4f_vertexbuffer = 0;
9382 rsurface.passcolor4f_bufferoffset = 0;
9383 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)
9385 f = -DotProduct(r_refdef.view.forward, n);
9387 f = f * 0.85 + 0.15; // work around so stuff won't get black
9388 f *= r_refdef.lightmapintensity;
9389 Vector4Set(c, f, f, f, 1);
9393 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9395 RSurf_DrawBatch_GL11_ApplyFakeLight();
9396 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9397 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9398 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9399 GL_Color(r, g, b, a);
9403 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9411 vec3_t ambientcolor;
9412 vec3_t diffusecolor;
9416 VectorCopy(rsurface.modellight_lightdir, lightdir);
9417 f = 0.5f * r_refdef.lightmapintensity;
9418 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9419 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9420 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9421 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9422 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9423 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9425 if (VectorLength2(diffusecolor) > 0)
9427 // q3-style directional shading
9428 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9429 rsurface.passcolor4f_vertexbuffer = 0;
9430 rsurface.passcolor4f_bufferoffset = 0;
9431 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)
9433 if ((f = DotProduct(n, lightdir)) > 0)
9434 VectorMA(ambientcolor, f, diffusecolor, c);
9436 VectorCopy(ambientcolor, c);
9443 *applycolor = false;
9447 *r = ambientcolor[0];
9448 *g = ambientcolor[1];
9449 *b = ambientcolor[2];
9450 rsurface.passcolor4f = NULL;
9451 rsurface.passcolor4f_vertexbuffer = 0;
9452 rsurface.passcolor4f_bufferoffset = 0;
9456 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9458 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9459 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9460 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9461 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9462 GL_Color(r, g, b, a);
9466 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9474 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9475 rsurface.passcolor4f_vertexbuffer = 0;
9476 rsurface.passcolor4f_bufferoffset = 0;
9478 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9480 f = 1 - RSurf_FogVertex(v);
9488 void RSurf_SetupDepthAndCulling(void)
9490 // submodels are biased to avoid z-fighting with world surfaces that they
9491 // may be exactly overlapping (avoids z-fighting artifacts on certain
9492 // doors and things in Quake maps)
9493 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9494 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9495 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9496 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9499 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9501 // transparent sky would be ridiculous
9502 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9504 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9505 skyrenderlater = true;
9506 RSurf_SetupDepthAndCulling();
9508 // LordHavoc: HalfLife maps have freaky skypolys so don't use
9509 // skymasking on them, and Quake3 never did sky masking (unlike
9510 // software Quake and software Quake2), so disable the sky masking
9511 // in Quake3 maps as it causes problems with q3map2 sky tricks,
9512 // and skymasking also looks very bad when noclipping outside the
9513 // level, so don't use it then either.
9514 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9516 R_Mesh_ResetTextureState();
9517 if (skyrendermasked)
9519 R_SetupShader_DepthOrShadow();
9520 // depth-only (masking)
9521 GL_ColorMask(0,0,0,0);
9522 // just to make sure that braindead drivers don't draw
9523 // anything despite that colormask...
9524 GL_BlendFunc(GL_ZERO, GL_ONE);
9525 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9526 if (rsurface.batchvertex3fbuffer)
9527 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9529 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9533 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9535 GL_BlendFunc(GL_ONE, GL_ZERO);
9536 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9537 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9538 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9541 if (skyrendermasked)
9542 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9544 R_Mesh_ResetTextureState();
9545 GL_Color(1, 1, 1, 1);
9548 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9549 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9550 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9552 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9556 // render screenspace normalmap to texture
9558 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9562 // bind lightmap texture
9564 // water/refraction/reflection/camera surfaces have to be handled specially
9565 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9567 int start, end, startplaneindex;
9568 for (start = 0;start < texturenumsurfaces;start = end)
9570 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9571 if(startplaneindex < 0)
9573 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9574 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9578 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9580 // now that we have a batch using the same planeindex, render it
9581 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9583 // render water or distortion background
9585 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));
9587 // blend surface on top
9588 GL_DepthMask(false);
9589 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9592 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9594 // render surface with reflection texture as input
9595 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9596 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));
9603 // render surface batch normally
9604 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9605 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
9606 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9609 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9610 GL_AlphaTest(false);
9613 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9615 // OpenGL 1.3 path - anything not completely ancient
9616 qboolean applycolor;
9619 const texturelayer_t *layer;
9620 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);
9621 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9623 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9626 int layertexrgbscale;
9627 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9629 if (layerindex == 0)
9633 GL_AlphaTest(false);
9634 GL_DepthFunc(GL_EQUAL);
9637 GL_DepthMask(layer->depthmask && writedepth);
9638 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9639 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9641 layertexrgbscale = 4;
9642 VectorScale(layer->color, 0.25f, layercolor);
9644 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9646 layertexrgbscale = 2;
9647 VectorScale(layer->color, 0.5f, layercolor);
9651 layertexrgbscale = 1;
9652 VectorScale(layer->color, 1.0f, layercolor);
9654 layercolor[3] = layer->color[3];
9655 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9656 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9657 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9658 switch (layer->type)
9660 case TEXTURELAYERTYPE_LITTEXTURE:
9661 // single-pass lightmapped texture with 2x rgbscale
9662 R_Mesh_TexBind(0, r_texture_white);
9663 R_Mesh_TexMatrix(0, NULL);
9664 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9665 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9666 R_Mesh_TexBind(1, layer->texture);
9667 R_Mesh_TexMatrix(1, &layer->texmatrix);
9668 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9669 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9670 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9671 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9672 else if (FAKELIGHT_ENABLED)
9673 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9674 else if (rsurface.uselightmaptexture)
9675 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9677 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9679 case TEXTURELAYERTYPE_TEXTURE:
9680 // singletexture unlit texture with transparency support
9681 R_Mesh_TexBind(0, layer->texture);
9682 R_Mesh_TexMatrix(0, &layer->texmatrix);
9683 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9684 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9685 R_Mesh_TexBind(1, 0);
9686 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9687 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9689 case TEXTURELAYERTYPE_FOG:
9690 // singletexture fogging
9693 R_Mesh_TexBind(0, layer->texture);
9694 R_Mesh_TexMatrix(0, &layer->texmatrix);
9695 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9696 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9700 R_Mesh_TexBind(0, 0);
9701 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9703 R_Mesh_TexBind(1, 0);
9704 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9705 // generate a color array for the fog pass
9706 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9707 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9711 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9714 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9716 GL_DepthFunc(GL_LEQUAL);
9717 GL_AlphaTest(false);
9721 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9723 // OpenGL 1.1 - crusty old voodoo path
9726 const texturelayer_t *layer;
9727 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);
9728 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9730 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9732 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9734 if (layerindex == 0)
9738 GL_AlphaTest(false);
9739 GL_DepthFunc(GL_EQUAL);
9742 GL_DepthMask(layer->depthmask && writedepth);
9743 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9744 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9745 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9746 switch (layer->type)
9748 case TEXTURELAYERTYPE_LITTEXTURE:
9749 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9751 // two-pass lit texture with 2x rgbscale
9752 // first the lightmap pass
9753 R_Mesh_TexBind(0, r_texture_white);
9754 R_Mesh_TexMatrix(0, NULL);
9755 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9756 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9757 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9758 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9759 else if (FAKELIGHT_ENABLED)
9760 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9761 else if (rsurface.uselightmaptexture)
9762 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9764 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9765 // then apply the texture to it
9766 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9767 R_Mesh_TexBind(0, layer->texture);
9768 R_Mesh_TexMatrix(0, &layer->texmatrix);
9769 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9770 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9771 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);
9775 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9776 R_Mesh_TexBind(0, layer->texture);
9777 R_Mesh_TexMatrix(0, &layer->texmatrix);
9778 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9779 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9780 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9781 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);
9783 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);
9786 case TEXTURELAYERTYPE_TEXTURE:
9787 // singletexture unlit texture with transparency support
9788 R_Mesh_TexBind(0, layer->texture);
9789 R_Mesh_TexMatrix(0, &layer->texmatrix);
9790 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9791 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9792 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);
9794 case TEXTURELAYERTYPE_FOG:
9795 // singletexture fogging
9798 R_Mesh_TexBind(0, layer->texture);
9799 R_Mesh_TexMatrix(0, &layer->texmatrix);
9800 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9801 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9805 R_Mesh_TexBind(0, 0);
9806 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9808 // generate a color array for the fog pass
9809 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9810 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9814 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9817 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9819 GL_DepthFunc(GL_LEQUAL);
9820 GL_AlphaTest(false);
9824 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9828 r_vertexgeneric_t *batchvertex;
9831 // R_Mesh_ResetTextureState();
9832 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9834 if(rsurface.texture && rsurface.texture->currentskinframe)
9836 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9837 c[3] *= rsurface.texture->currentalpha;
9847 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9849 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9850 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9851 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9854 // brighten it up (as texture value 127 means "unlit")
9855 c[0] *= 2 * r_refdef.view.colorscale;
9856 c[1] *= 2 * r_refdef.view.colorscale;
9857 c[2] *= 2 * r_refdef.view.colorscale;
9859 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9860 c[3] *= r_wateralpha.value;
9862 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9864 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9865 GL_DepthMask(false);
9867 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9869 GL_BlendFunc(GL_ONE, GL_ONE);
9870 GL_DepthMask(false);
9872 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9874 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9875 GL_DepthMask(false);
9877 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9879 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9880 GL_DepthMask(false);
9884 GL_BlendFunc(GL_ONE, GL_ZERO);
9885 GL_DepthMask(writedepth);
9888 if (r_showsurfaces.integer == 3)
9890 rsurface.passcolor4f = NULL;
9892 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9894 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9896 rsurface.passcolor4f = NULL;
9897 rsurface.passcolor4f_vertexbuffer = 0;
9898 rsurface.passcolor4f_bufferoffset = 0;
9900 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9902 qboolean applycolor = true;
9905 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9907 r_refdef.lightmapintensity = 1;
9908 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9909 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9911 else if (FAKELIGHT_ENABLED)
9913 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9915 r_refdef.lightmapintensity = r_fakelight_intensity.value;
9916 RSurf_DrawBatch_GL11_ApplyFakeLight();
9917 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9921 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9923 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9924 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9925 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9928 if(!rsurface.passcolor4f)
9929 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9931 RSurf_DrawBatch_GL11_ApplyAmbient();
9932 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9933 if(r_refdef.fogenabled)
9934 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9935 RSurf_DrawBatch_GL11_ClampColor();
9937 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9938 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9941 else if (!r_refdef.view.showdebug)
9943 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9944 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9945 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9947 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9948 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9950 R_Mesh_PrepareVertices_Generic_Unlock();
9953 else if (r_showsurfaces.integer == 4)
9955 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9956 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9957 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9959 unsigned char c = (vi << 3) * (1.0f / 256.0f);
9960 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9961 Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9963 R_Mesh_PrepareVertices_Generic_Unlock();
9966 else if (r_showsurfaces.integer == 2)
9969 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9970 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9971 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9973 unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9974 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9975 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9976 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9977 Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9978 Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9979 Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9981 R_Mesh_PrepareVertices_Generic_Unlock();
9982 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9986 int texturesurfaceindex;
9988 const msurface_t *surface;
9989 float surfacecolor4f[4];
9990 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9991 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9993 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9995 surface = texturesurfacelist[texturesurfaceindex];
9996 k = (int)(((size_t)surface) / sizeof(msurface_t));
9997 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9998 for (j = 0;j < surface->num_vertices;j++)
10000 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10001 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10005 R_Mesh_PrepareVertices_Generic_Unlock();
10010 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10013 RSurf_SetupDepthAndCulling();
10014 if (r_showsurfaces.integer)
10016 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10019 switch (vid.renderpath)
10021 case RENDERPATH_GL20:
10022 case RENDERPATH_D3D9:
10023 case RENDERPATH_D3D10:
10024 case RENDERPATH_D3D11:
10025 case RENDERPATH_SOFT:
10026 case RENDERPATH_GLES2:
10027 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10029 case RENDERPATH_GL13:
10030 case RENDERPATH_GLES1:
10031 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10033 case RENDERPATH_GL11:
10034 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10040 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10043 RSurf_SetupDepthAndCulling();
10044 if (r_showsurfaces.integer)
10046 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10049 switch (vid.renderpath)
10051 case RENDERPATH_GL20:
10052 case RENDERPATH_D3D9:
10053 case RENDERPATH_D3D10:
10054 case RENDERPATH_D3D11:
10055 case RENDERPATH_SOFT:
10056 case RENDERPATH_GLES2:
10057 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10059 case RENDERPATH_GL13:
10060 case RENDERPATH_GLES1:
10061 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10063 case RENDERPATH_GL11:
10064 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10070 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10073 int texturenumsurfaces, endsurface;
10074 texture_t *texture;
10075 const msurface_t *surface;
10076 const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10078 // if the model is static it doesn't matter what value we give for
10079 // wantnormals and wanttangents, so this logic uses only rules applicable
10080 // to a model, knowing that they are meaningless otherwise
10081 if (ent == r_refdef.scene.worldentity)
10082 RSurf_ActiveWorldEntity();
10083 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10084 RSurf_ActiveModelEntity(ent, false, false, false);
10087 switch (vid.renderpath)
10089 case RENDERPATH_GL20:
10090 case RENDERPATH_D3D9:
10091 case RENDERPATH_D3D10:
10092 case RENDERPATH_D3D11:
10093 case RENDERPATH_SOFT:
10094 case RENDERPATH_GLES2:
10095 RSurf_ActiveModelEntity(ent, true, true, false);
10097 case RENDERPATH_GL11:
10098 case RENDERPATH_GL13:
10099 case RENDERPATH_GLES1:
10100 RSurf_ActiveModelEntity(ent, true, false, false);
10105 if (r_transparentdepthmasking.integer)
10107 qboolean setup = false;
10108 for (i = 0;i < numsurfaces;i = j)
10111 surface = rsurface.modelsurfaces + surfacelist[i];
10112 texture = surface->texture;
10113 rsurface.texture = R_GetCurrentTexture(texture);
10114 rsurface.lightmaptexture = NULL;
10115 rsurface.deluxemaptexture = NULL;
10116 rsurface.uselightmaptexture = false;
10117 // scan ahead until we find a different texture
10118 endsurface = min(i + 1024, numsurfaces);
10119 texturenumsurfaces = 0;
10120 texturesurfacelist[texturenumsurfaces++] = surface;
10121 for (;j < endsurface;j++)
10123 surface = rsurface.modelsurfaces + surfacelist[j];
10124 if (texture != surface->texture)
10126 texturesurfacelist[texturenumsurfaces++] = surface;
10128 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10130 // render the range of surfaces as depth
10134 GL_ColorMask(0,0,0,0);
10136 GL_DepthTest(true);
10137 GL_BlendFunc(GL_ONE, GL_ZERO);
10138 GL_DepthMask(true);
10139 // R_Mesh_ResetTextureState();
10140 R_SetupShader_DepthOrShadow();
10142 RSurf_SetupDepthAndCulling();
10143 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10144 if (rsurface.batchvertex3fbuffer)
10145 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10147 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10151 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10154 for (i = 0;i < numsurfaces;i = j)
10157 surface = rsurface.modelsurfaces + surfacelist[i];
10158 texture = surface->texture;
10159 rsurface.texture = R_GetCurrentTexture(texture);
10160 // scan ahead until we find a different texture
10161 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10162 texturenumsurfaces = 0;
10163 texturesurfacelist[texturenumsurfaces++] = surface;
10164 if(FAKELIGHT_ENABLED)
10166 rsurface.lightmaptexture = NULL;
10167 rsurface.deluxemaptexture = NULL;
10168 rsurface.uselightmaptexture = false;
10169 for (;j < endsurface;j++)
10171 surface = rsurface.modelsurfaces + surfacelist[j];
10172 if (texture != surface->texture)
10174 texturesurfacelist[texturenumsurfaces++] = surface;
10179 rsurface.lightmaptexture = surface->lightmaptexture;
10180 rsurface.deluxemaptexture = surface->deluxemaptexture;
10181 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10182 for (;j < endsurface;j++)
10184 surface = rsurface.modelsurfaces + surfacelist[j];
10185 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10187 texturesurfacelist[texturenumsurfaces++] = surface;
10190 // render the range of surfaces
10191 if (ent == r_refdef.scene.worldentity)
10192 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10194 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10196 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10199 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10201 // transparent surfaces get pushed off into the transparent queue
10202 int surfacelistindex;
10203 const msurface_t *surface;
10204 vec3_t tempcenter, center;
10205 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10207 surface = texturesurfacelist[surfacelistindex];
10208 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10209 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10210 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10211 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10212 if (queueentity->transparent_offset) // transparent offset
10214 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10215 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10216 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10218 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10222 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10224 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10226 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10228 RSurf_SetupDepthAndCulling();
10229 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10230 if (rsurface.batchvertex3fbuffer)
10231 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10233 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10237 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10239 const entity_render_t *queueentity = r_refdef.scene.worldentity;
10242 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10245 if (!rsurface.texture->currentnumlayers)
10247 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10248 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10250 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10252 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10253 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10254 else if (!rsurface.texture->currentnumlayers)
10256 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10258 // in the deferred case, transparent surfaces were queued during prepass
10259 if (!r_shadow_usingdeferredprepass)
10260 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10264 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10265 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10270 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10273 texture_t *texture;
10274 R_FrameData_SetMark();
10275 // break the surface list down into batches by texture and use of lightmapping
10276 for (i = 0;i < numsurfaces;i = j)
10279 // texture is the base texture pointer, rsurface.texture is the
10280 // current frame/skin the texture is directing us to use (for example
10281 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10282 // use skin 1 instead)
10283 texture = surfacelist[i]->texture;
10284 rsurface.texture = R_GetCurrentTexture(texture);
10285 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10287 // if this texture is not the kind we want, skip ahead to the next one
10288 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10292 if(FAKELIGHT_ENABLED || depthonly || prepass)
10294 rsurface.lightmaptexture = NULL;
10295 rsurface.deluxemaptexture = NULL;
10296 rsurface.uselightmaptexture = false;
10297 // simply scan ahead until we find a different texture or lightmap state
10298 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10303 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10304 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10305 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10306 // simply scan ahead until we find a different texture or lightmap state
10307 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10310 // render the range of surfaces
10311 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10313 R_FrameData_ReturnToMark();
10316 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10320 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10323 if (!rsurface.texture->currentnumlayers)
10325 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10326 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10328 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10330 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10331 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10332 else if (!rsurface.texture->currentnumlayers)
10334 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10336 // in the deferred case, transparent surfaces were queued during prepass
10337 if (!r_shadow_usingdeferredprepass)
10338 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10342 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10343 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10348 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10351 texture_t *texture;
10352 R_FrameData_SetMark();
10353 // break the surface list down into batches by texture and use of lightmapping
10354 for (i = 0;i < numsurfaces;i = j)
10357 // texture is the base texture pointer, rsurface.texture is the
10358 // current frame/skin the texture is directing us to use (for example
10359 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10360 // use skin 1 instead)
10361 texture = surfacelist[i]->texture;
10362 rsurface.texture = R_GetCurrentTexture(texture);
10363 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10365 // if this texture is not the kind we want, skip ahead to the next one
10366 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10370 if(FAKELIGHT_ENABLED || depthonly || prepass)
10372 rsurface.lightmaptexture = NULL;
10373 rsurface.deluxemaptexture = NULL;
10374 rsurface.uselightmaptexture = false;
10375 // simply scan ahead until we find a different texture or lightmap state
10376 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10381 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10382 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10383 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10384 // simply scan ahead until we find a different texture or lightmap state
10385 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10388 // render the range of surfaces
10389 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10391 R_FrameData_ReturnToMark();
10394 float locboxvertex3f[6*4*3] =
10396 1,0,1, 1,0,0, 1,1,0, 1,1,1,
10397 0,1,1, 0,1,0, 0,0,0, 0,0,1,
10398 1,1,1, 1,1,0, 0,1,0, 0,1,1,
10399 0,0,1, 0,0,0, 1,0,0, 1,0,1,
10400 0,0,1, 1,0,1, 1,1,1, 0,1,1,
10401 1,0,0, 0,0,0, 0,1,0, 1,1,0
10404 unsigned short locboxelements[6*2*3] =
10409 12,13,14, 12,14,15,
10410 16,17,18, 16,18,19,
10414 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10417 cl_locnode_t *loc = (cl_locnode_t *)ent;
10419 float vertex3f[6*4*3];
10421 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10422 GL_DepthMask(false);
10423 GL_DepthRange(0, 1);
10424 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10425 GL_DepthTest(true);
10426 GL_CullFace(GL_NONE);
10427 R_EntityMatrix(&identitymatrix);
10429 // R_Mesh_ResetTextureState();
10431 i = surfacelist[0];
10432 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10433 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10434 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10435 surfacelist[0] < 0 ? 0.5f : 0.125f);
10437 if (VectorCompare(loc->mins, loc->maxs))
10439 VectorSet(size, 2, 2, 2);
10440 VectorMA(loc->mins, -0.5f, size, mins);
10444 VectorCopy(loc->mins, mins);
10445 VectorSubtract(loc->maxs, loc->mins, size);
10448 for (i = 0;i < 6*4*3;)
10449 for (j = 0;j < 3;j++, i++)
10450 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10452 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10453 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10454 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10457 void R_DrawLocs(void)
10460 cl_locnode_t *loc, *nearestloc;
10462 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10463 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10465 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10466 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10470 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10472 if (decalsystem->decals)
10473 Mem_Free(decalsystem->decals);
10474 memset(decalsystem, 0, sizeof(*decalsystem));
10477 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)
10480 tridecal_t *decals;
10483 // expand or initialize the system
10484 if (decalsystem->maxdecals <= decalsystem->numdecals)
10486 decalsystem_t old = *decalsystem;
10487 qboolean useshortelements;
10488 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10489 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10490 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)));
10491 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10492 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10493 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10494 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10495 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10496 if (decalsystem->numdecals)
10497 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10499 Mem_Free(old.decals);
10500 for (i = 0;i < decalsystem->maxdecals*3;i++)
10501 decalsystem->element3i[i] = i;
10502 if (useshortelements)
10503 for (i = 0;i < decalsystem->maxdecals*3;i++)
10504 decalsystem->element3s[i] = i;
10507 // grab a decal and search for another free slot for the next one
10508 decals = decalsystem->decals;
10509 decal = decalsystem->decals + (i = decalsystem->freedecal++);
10510 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10512 decalsystem->freedecal = i;
10513 if (decalsystem->numdecals <= i)
10514 decalsystem->numdecals = i + 1;
10516 // initialize the decal
10518 decal->triangleindex = triangleindex;
10519 decal->surfaceindex = surfaceindex;
10520 decal->decalsequence = decalsequence;
10521 decal->color4f[0][0] = c0[0];
10522 decal->color4f[0][1] = c0[1];
10523 decal->color4f[0][2] = c0[2];
10524 decal->color4f[0][3] = 1;
10525 decal->color4f[1][0] = c1[0];
10526 decal->color4f[1][1] = c1[1];
10527 decal->color4f[1][2] = c1[2];
10528 decal->color4f[1][3] = 1;
10529 decal->color4f[2][0] = c2[0];
10530 decal->color4f[2][1] = c2[1];
10531 decal->color4f[2][2] = c2[2];
10532 decal->color4f[2][3] = 1;
10533 decal->vertex3f[0][0] = v0[0];
10534 decal->vertex3f[0][1] = v0[1];
10535 decal->vertex3f[0][2] = v0[2];
10536 decal->vertex3f[1][0] = v1[0];
10537 decal->vertex3f[1][1] = v1[1];
10538 decal->vertex3f[1][2] = v1[2];
10539 decal->vertex3f[2][0] = v2[0];
10540 decal->vertex3f[2][1] = v2[1];
10541 decal->vertex3f[2][2] = v2[2];
10542 decal->texcoord2f[0][0] = t0[0];
10543 decal->texcoord2f[0][1] = t0[1];
10544 decal->texcoord2f[1][0] = t1[0];
10545 decal->texcoord2f[1][1] = t1[1];
10546 decal->texcoord2f[2][0] = t2[0];
10547 decal->texcoord2f[2][1] = t2[1];
10548 TriangleNormal(v0, v1, v2, decal->plane);
10549 VectorNormalize(decal->plane);
10550 decal->plane[3] = DotProduct(v0, decal->plane);
10553 extern cvar_t cl_decals_bias;
10554 extern cvar_t cl_decals_models;
10555 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10556 // baseparms, parms, temps
10557 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)
10562 const float *vertex3f;
10563 const float *normal3f;
10565 float points[2][9][3];
10572 e = rsurface.modelelement3i + 3*triangleindex;
10574 vertex3f = rsurface.modelvertex3f;
10575 normal3f = rsurface.modelnormal3f;
10579 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10581 index = 3*e[cornerindex];
10582 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10587 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10589 index = 3*e[cornerindex];
10590 VectorCopy(vertex3f + index, v[cornerindex]);
10595 //TriangleNormal(v[0], v[1], v[2], normal);
10596 //if (DotProduct(normal, localnormal) < 0.0f)
10598 // clip by each of the box planes formed from the projection matrix
10599 // if anything survives, we emit the decal
10600 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]);
10603 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]);
10606 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]);
10609 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]);
10612 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]);
10615 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]);
10618 // some part of the triangle survived, so we have to accept it...
10621 // dynamic always uses the original triangle
10623 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10625 index = 3*e[cornerindex];
10626 VectorCopy(vertex3f + index, v[cornerindex]);
10629 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10631 // convert vertex positions to texcoords
10632 Matrix4x4_Transform(projection, v[cornerindex], temp);
10633 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10634 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10635 // calculate distance fade from the projection origin
10636 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10637 f = bound(0.0f, f, 1.0f);
10638 c[cornerindex][0] = r * f;
10639 c[cornerindex][1] = g * f;
10640 c[cornerindex][2] = b * f;
10641 c[cornerindex][3] = 1.0f;
10642 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10645 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);
10647 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10648 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);
10650 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)
10652 matrix4x4_t projection;
10653 decalsystem_t *decalsystem;
10656 const msurface_t *surface;
10657 const msurface_t *surfaces;
10658 const int *surfacelist;
10659 const texture_t *texture;
10661 int numsurfacelist;
10662 int surfacelistindex;
10665 float localorigin[3];
10666 float localnormal[3];
10667 float localmins[3];
10668 float localmaxs[3];
10671 float planes[6][4];
10674 int bih_triangles_count;
10675 int bih_triangles[256];
10676 int bih_surfaces[256];
10678 decalsystem = &ent->decalsystem;
10679 model = ent->model;
10680 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10682 R_DecalSystem_Reset(&ent->decalsystem);
10686 if (!model->brush.data_leafs && !cl_decals_models.integer)
10688 if (decalsystem->model)
10689 R_DecalSystem_Reset(decalsystem);
10693 if (decalsystem->model != model)
10694 R_DecalSystem_Reset(decalsystem);
10695 decalsystem->model = model;
10697 RSurf_ActiveModelEntity(ent, true, false, false);
10699 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10700 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10701 VectorNormalize(localnormal);
10702 localsize = worldsize*rsurface.inversematrixscale;
10703 localmins[0] = localorigin[0] - localsize;
10704 localmins[1] = localorigin[1] - localsize;
10705 localmins[2] = localorigin[2] - localsize;
10706 localmaxs[0] = localorigin[0] + localsize;
10707 localmaxs[1] = localorigin[1] + localsize;
10708 localmaxs[2] = localorigin[2] + localsize;
10710 //VectorCopy(localnormal, planes[4]);
10711 //VectorVectors(planes[4], planes[2], planes[0]);
10712 AnglesFromVectors(angles, localnormal, NULL, false);
10713 AngleVectors(angles, planes[0], planes[2], planes[4]);
10714 VectorNegate(planes[0], planes[1]);
10715 VectorNegate(planes[2], planes[3]);
10716 VectorNegate(planes[4], planes[5]);
10717 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10718 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10719 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10720 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10721 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10722 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10727 matrix4x4_t forwardprojection;
10728 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10729 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10734 float projectionvector[4][3];
10735 VectorScale(planes[0], ilocalsize, projectionvector[0]);
10736 VectorScale(planes[2], ilocalsize, projectionvector[1]);
10737 VectorScale(planes[4], ilocalsize, projectionvector[2]);
10738 projectionvector[0][0] = planes[0][0] * ilocalsize;
10739 projectionvector[0][1] = planes[1][0] * ilocalsize;
10740 projectionvector[0][2] = planes[2][0] * ilocalsize;
10741 projectionvector[1][0] = planes[0][1] * ilocalsize;
10742 projectionvector[1][1] = planes[1][1] * ilocalsize;
10743 projectionvector[1][2] = planes[2][1] * ilocalsize;
10744 projectionvector[2][0] = planes[0][2] * ilocalsize;
10745 projectionvector[2][1] = planes[1][2] * ilocalsize;
10746 projectionvector[2][2] = planes[2][2] * ilocalsize;
10747 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10748 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10749 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10750 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10754 dynamic = model->surfmesh.isanimated;
10755 numsurfacelist = model->nummodelsurfaces;
10756 surfacelist = model->sortedmodelsurfaces;
10757 surfaces = model->data_surfaces;
10760 bih_triangles_count = -1;
10763 if(model->render_bih.numleafs)
10764 bih = &model->render_bih;
10765 else if(model->collision_bih.numleafs)
10766 bih = &model->collision_bih;
10769 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10770 if(bih_triangles_count == 0)
10772 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10774 if(bih_triangles_count > 0)
10776 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10778 surfaceindex = bih_surfaces[triangleindex];
10779 surface = surfaces + surfaceindex;
10780 texture = surface->texture;
10781 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10783 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10785 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10790 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10792 surfaceindex = surfacelist[surfacelistindex];
10793 surface = surfaces + surfaceindex;
10794 // check cull box first because it rejects more than any other check
10795 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10797 // skip transparent surfaces
10798 texture = surface->texture;
10799 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10801 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10803 numtriangles = surface->num_triangles;
10804 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10805 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10810 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10811 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)
10813 int renderentityindex;
10814 float worldmins[3];
10815 float worldmaxs[3];
10816 entity_render_t *ent;
10818 if (!cl_decals_newsystem.integer)
10821 worldmins[0] = worldorigin[0] - worldsize;
10822 worldmins[1] = worldorigin[1] - worldsize;
10823 worldmins[2] = worldorigin[2] - worldsize;
10824 worldmaxs[0] = worldorigin[0] + worldsize;
10825 worldmaxs[1] = worldorigin[1] + worldsize;
10826 worldmaxs[2] = worldorigin[2] + worldsize;
10828 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10830 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10832 ent = r_refdef.scene.entities[renderentityindex];
10833 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10836 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10840 typedef struct r_decalsystem_splatqueue_s
10842 vec3_t worldorigin;
10843 vec3_t worldnormal;
10849 r_decalsystem_splatqueue_t;
10851 int r_decalsystem_numqueued = 0;
10852 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10854 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)
10856 r_decalsystem_splatqueue_t *queue;
10858 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10861 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10862 VectorCopy(worldorigin, queue->worldorigin);
10863 VectorCopy(worldnormal, queue->worldnormal);
10864 Vector4Set(queue->color, r, g, b, a);
10865 Vector4Set(queue->tcrange, s1, t1, s2, t2);
10866 queue->worldsize = worldsize;
10867 queue->decalsequence = cl.decalsequence++;
10870 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10873 r_decalsystem_splatqueue_t *queue;
10875 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10876 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);
10877 r_decalsystem_numqueued = 0;
10880 extern cvar_t cl_decals_max;
10881 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10884 decalsystem_t *decalsystem = &ent->decalsystem;
10891 if (!decalsystem->numdecals)
10894 if (r_showsurfaces.integer)
10897 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10899 R_DecalSystem_Reset(decalsystem);
10903 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10904 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10906 if (decalsystem->lastupdatetime)
10907 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
10910 decalsystem->lastupdatetime = r_refdef.scene.time;
10911 decal = decalsystem->decals;
10912 numdecals = decalsystem->numdecals;
10914 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10916 if (decal->color4f[0][3])
10918 decal->lived += frametime;
10919 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10921 memset(decal, 0, sizeof(*decal));
10922 if (decalsystem->freedecal > i)
10923 decalsystem->freedecal = i;
10927 decal = decalsystem->decals;
10928 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10931 // collapse the array by shuffling the tail decals into the gaps
10934 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10935 decalsystem->freedecal++;
10936 if (decalsystem->freedecal == numdecals)
10938 decal[decalsystem->freedecal] = decal[--numdecals];
10941 decalsystem->numdecals = numdecals;
10943 if (numdecals <= 0)
10945 // if there are no decals left, reset decalsystem
10946 R_DecalSystem_Reset(decalsystem);
10950 extern skinframe_t *decalskinframe;
10951 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10954 decalsystem_t *decalsystem = &ent->decalsystem;
10963 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10966 numdecals = decalsystem->numdecals;
10970 if (r_showsurfaces.integer)
10973 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10975 R_DecalSystem_Reset(decalsystem);
10979 // if the model is static it doesn't matter what value we give for
10980 // wantnormals and wanttangents, so this logic uses only rules applicable
10981 // to a model, knowing that they are meaningless otherwise
10982 if (ent == r_refdef.scene.worldentity)
10983 RSurf_ActiveWorldEntity();
10985 RSurf_ActiveModelEntity(ent, false, false, false);
10987 decalsystem->lastupdatetime = r_refdef.scene.time;
10988 decal = decalsystem->decals;
10990 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10992 // update vertex positions for animated models
10993 v3f = decalsystem->vertex3f;
10994 c4f = decalsystem->color4f;
10995 t2f = decalsystem->texcoord2f;
10996 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10998 if (!decal->color4f[0][3])
11001 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11005 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11008 // update color values for fading decals
11009 if (decal->lived >= cl_decals_time.value)
11010 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11014 c4f[ 0] = decal->color4f[0][0] * alpha;
11015 c4f[ 1] = decal->color4f[0][1] * alpha;
11016 c4f[ 2] = decal->color4f[0][2] * alpha;
11018 c4f[ 4] = decal->color4f[1][0] * alpha;
11019 c4f[ 5] = decal->color4f[1][1] * alpha;
11020 c4f[ 6] = decal->color4f[1][2] * alpha;
11022 c4f[ 8] = decal->color4f[2][0] * alpha;
11023 c4f[ 9] = decal->color4f[2][1] * alpha;
11024 c4f[10] = decal->color4f[2][2] * alpha;
11027 t2f[0] = decal->texcoord2f[0][0];
11028 t2f[1] = decal->texcoord2f[0][1];
11029 t2f[2] = decal->texcoord2f[1][0];
11030 t2f[3] = decal->texcoord2f[1][1];
11031 t2f[4] = decal->texcoord2f[2][0];
11032 t2f[5] = decal->texcoord2f[2][1];
11034 // update vertex positions for animated models
11035 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11037 e = rsurface.modelelement3i + 3*decal->triangleindex;
11038 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11039 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11040 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11044 VectorCopy(decal->vertex3f[0], v3f);
11045 VectorCopy(decal->vertex3f[1], v3f + 3);
11046 VectorCopy(decal->vertex3f[2], v3f + 6);
11049 if (r_refdef.fogenabled)
11051 alpha = RSurf_FogVertex(v3f);
11052 VectorScale(c4f, alpha, c4f);
11053 alpha = RSurf_FogVertex(v3f + 3);
11054 VectorScale(c4f + 4, alpha, c4f + 4);
11055 alpha = RSurf_FogVertex(v3f + 6);
11056 VectorScale(c4f + 8, alpha, c4f + 8);
11067 r_refdef.stats.drawndecals += numtris;
11069 // now render the decals all at once
11070 // (this assumes they all use one particle font texture!)
11071 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);
11072 // R_Mesh_ResetTextureState();
11073 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11074 GL_DepthMask(false);
11075 GL_DepthRange(0, 1);
11076 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11077 GL_DepthTest(true);
11078 GL_CullFace(GL_NONE);
11079 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11080 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
11081 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11085 static void R_DrawModelDecals(void)
11089 // fade faster when there are too many decals
11090 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11091 for (i = 0;i < r_refdef.scene.numentities;i++)
11092 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11094 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11095 for (i = 0;i < r_refdef.scene.numentities;i++)
11096 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11097 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11099 R_DecalSystem_ApplySplatEntitiesQueue();
11101 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11102 for (i = 0;i < r_refdef.scene.numentities;i++)
11103 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11105 r_refdef.stats.totaldecals += numdecals;
11107 if (r_showsurfaces.integer)
11110 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11112 for (i = 0;i < r_refdef.scene.numentities;i++)
11114 if (!r_refdef.viewcache.entityvisible[i])
11116 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11117 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11121 extern cvar_t mod_collision_bih;
11122 void R_DrawDebugModel(void)
11124 entity_render_t *ent = rsurface.entity;
11125 int i, j, k, l, flagsmask;
11126 const msurface_t *surface;
11127 dp_model_t *model = ent->model;
11130 if (!sv.active && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11133 if (r_showoverdraw.value > 0)
11135 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11136 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11137 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11138 GL_DepthTest(false);
11139 GL_DepthMask(false);
11140 GL_DepthRange(0, 1);
11141 GL_BlendFunc(GL_ONE, GL_ONE);
11142 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11144 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11146 rsurface.texture = R_GetCurrentTexture(surface->texture);
11147 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11149 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11150 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11151 if (!rsurface.texture->currentlayers->depthmask)
11152 GL_Color(c, 0, 0, 1.0f);
11153 else if (ent == r_refdef.scene.worldentity)
11154 GL_Color(c, c, c, 1.0f);
11156 GL_Color(0, c, 0, 1.0f);
11157 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11161 rsurface.texture = NULL;
11164 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11166 // R_Mesh_ResetTextureState();
11167 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11168 GL_DepthRange(0, 1);
11169 GL_DepthTest(!r_showdisabledepthtest.integer);
11170 GL_DepthMask(false);
11171 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11173 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11177 qboolean cullbox = ent == r_refdef.scene.worldentity;
11178 const q3mbrush_t *brush;
11179 const bih_t *bih = &model->collision_bih;
11180 const bih_leaf_t *bihleaf;
11181 float vertex3f[3][3];
11182 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11184 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11186 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11188 switch (bihleaf->type)
11191 brush = model->brush.data_brushes + bihleaf->itemindex;
11192 if (brush->colbrushf && brush->colbrushf->numtriangles)
11194 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);
11195 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11196 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11199 case BIH_COLLISIONTRIANGLE:
11200 triangleindex = bihleaf->itemindex;
11201 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11202 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11203 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11204 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);
11205 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11206 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11208 case BIH_RENDERTRIANGLE:
11209 triangleindex = bihleaf->itemindex;
11210 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11211 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11212 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11213 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);
11214 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11215 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11221 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11223 if (r_showtris.integer && qglPolygonMode)
11225 if (r_showdisabledepthtest.integer)
11227 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11228 GL_DepthMask(false);
11232 GL_BlendFunc(GL_ONE, GL_ZERO);
11233 GL_DepthMask(true);
11235 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11236 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11238 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11240 rsurface.texture = R_GetCurrentTexture(surface->texture);
11241 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11243 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11244 if (!rsurface.texture->currentlayers->depthmask)
11245 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11246 else if (ent == r_refdef.scene.worldentity)
11247 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11249 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11250 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11254 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11255 rsurface.texture = NULL;
11258 if (r_shownormals.value != 0 && qglBegin)
11260 if (r_showdisabledepthtest.integer)
11262 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11263 GL_DepthMask(false);
11267 GL_BlendFunc(GL_ONE, GL_ZERO);
11268 GL_DepthMask(true);
11270 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11272 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11274 rsurface.texture = R_GetCurrentTexture(surface->texture);
11275 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11277 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11278 qglBegin(GL_LINES);
11279 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11281 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11283 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11284 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11285 qglVertex3f(v[0], v[1], v[2]);
11286 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11287 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11288 qglVertex3f(v[0], v[1], v[2]);
11291 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11293 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11295 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11296 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11297 qglVertex3f(v[0], v[1], v[2]);
11298 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11299 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11300 qglVertex3f(v[0], v[1], v[2]);
11303 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11305 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11307 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11308 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11309 qglVertex3f(v[0], v[1], v[2]);
11310 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11311 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11312 qglVertex3f(v[0], v[1], v[2]);
11315 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11317 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11319 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11320 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11321 qglVertex3f(v[0], v[1], v[2]);
11322 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11323 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11324 qglVertex3f(v[0], v[1], v[2]);
11331 rsurface.texture = NULL;
11335 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11336 int r_maxsurfacelist = 0;
11337 const msurface_t **r_surfacelist = NULL;
11338 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11340 int i, j, endj, flagsmask;
11341 dp_model_t *model = r_refdef.scene.worldmodel;
11342 msurface_t *surfaces;
11343 unsigned char *update;
11344 int numsurfacelist = 0;
11348 if (r_maxsurfacelist < model->num_surfaces)
11350 r_maxsurfacelist = model->num_surfaces;
11352 Mem_Free((msurface_t**)r_surfacelist);
11353 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11356 RSurf_ActiveWorldEntity();
11358 surfaces = model->data_surfaces;
11359 update = model->brushq1.lightmapupdateflags;
11361 // update light styles on this submodel
11362 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11364 model_brush_lightstyleinfo_t *style;
11365 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11367 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11369 int *list = style->surfacelist;
11370 style->value = r_refdef.scene.lightstylevalue[style->style];
11371 for (j = 0;j < style->numsurfaces;j++)
11372 update[list[j]] = true;
11377 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11381 R_DrawDebugModel();
11382 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11386 rsurface.lightmaptexture = NULL;
11387 rsurface.deluxemaptexture = NULL;
11388 rsurface.uselightmaptexture = false;
11389 rsurface.texture = NULL;
11390 rsurface.rtlight = NULL;
11391 numsurfacelist = 0;
11392 // add visible surfaces to draw list
11393 for (i = 0;i < model->nummodelsurfaces;i++)
11395 j = model->sortedmodelsurfaces[i];
11396 if (r_refdef.viewcache.world_surfacevisible[j])
11397 r_surfacelist[numsurfacelist++] = surfaces + j;
11399 // update lightmaps if needed
11400 if (model->brushq1.firstrender)
11402 model->brushq1.firstrender = false;
11403 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11405 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11409 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11410 if (r_refdef.viewcache.world_surfacevisible[j])
11412 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11414 // don't do anything if there were no surfaces
11415 if (!numsurfacelist)
11417 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11420 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11422 // add to stats if desired
11423 if (r_speeds.integer && !skysurfaces && !depthonly)
11425 r_refdef.stats.world_surfaces += numsurfacelist;
11426 for (j = 0;j < numsurfacelist;j++)
11427 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11430 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11433 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11435 int i, j, endj, flagsmask;
11436 dp_model_t *model = ent->model;
11437 msurface_t *surfaces;
11438 unsigned char *update;
11439 int numsurfacelist = 0;
11443 if (r_maxsurfacelist < model->num_surfaces)
11445 r_maxsurfacelist = model->num_surfaces;
11447 Mem_Free((msurface_t **)r_surfacelist);
11448 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11451 // if the model is static it doesn't matter what value we give for
11452 // wantnormals and wanttangents, so this logic uses only rules applicable
11453 // to a model, knowing that they are meaningless otherwise
11454 if (ent == r_refdef.scene.worldentity)
11455 RSurf_ActiveWorldEntity();
11456 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11457 RSurf_ActiveModelEntity(ent, false, false, false);
11459 RSurf_ActiveModelEntity(ent, true, true, true);
11460 else if (depthonly)
11462 switch (vid.renderpath)
11464 case RENDERPATH_GL20:
11465 case RENDERPATH_D3D9:
11466 case RENDERPATH_D3D10:
11467 case RENDERPATH_D3D11:
11468 case RENDERPATH_SOFT:
11469 case RENDERPATH_GLES2:
11470 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11472 case RENDERPATH_GL11:
11473 case RENDERPATH_GL13:
11474 case RENDERPATH_GLES1:
11475 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11481 switch (vid.renderpath)
11483 case RENDERPATH_GL20:
11484 case RENDERPATH_D3D9:
11485 case RENDERPATH_D3D10:
11486 case RENDERPATH_D3D11:
11487 case RENDERPATH_SOFT:
11488 case RENDERPATH_GLES2:
11489 RSurf_ActiveModelEntity(ent, true, true, false);
11491 case RENDERPATH_GL11:
11492 case RENDERPATH_GL13:
11493 case RENDERPATH_GLES1:
11494 RSurf_ActiveModelEntity(ent, true, false, false);
11499 surfaces = model->data_surfaces;
11500 update = model->brushq1.lightmapupdateflags;
11502 // update light styles
11503 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11505 model_brush_lightstyleinfo_t *style;
11506 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11508 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11510 int *list = style->surfacelist;
11511 style->value = r_refdef.scene.lightstylevalue[style->style];
11512 for (j = 0;j < style->numsurfaces;j++)
11513 update[list[j]] = true;
11518 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11522 R_DrawDebugModel();
11523 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11527 rsurface.lightmaptexture = NULL;
11528 rsurface.deluxemaptexture = NULL;
11529 rsurface.uselightmaptexture = false;
11530 rsurface.texture = NULL;
11531 rsurface.rtlight = NULL;
11532 numsurfacelist = 0;
11533 // add visible surfaces to draw list
11534 for (i = 0;i < model->nummodelsurfaces;i++)
11535 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11536 // don't do anything if there were no surfaces
11537 if (!numsurfacelist)
11539 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11542 // update lightmaps if needed
11546 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11551 R_BuildLightMap(ent, surfaces + j);
11556 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11558 R_BuildLightMap(ent, surfaces + j);
11559 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11561 // add to stats if desired
11562 if (r_speeds.integer && !skysurfaces && !depthonly)
11564 r_refdef.stats.entities_surfaces += numsurfacelist;
11565 for (j = 0;j < numsurfacelist;j++)
11566 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11569 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11572 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11574 static texture_t texture;
11575 static msurface_t surface;
11576 const msurface_t *surfacelist = &surface;
11578 // fake enough texture and surface state to render this geometry
11580 texture.update_lastrenderframe = -1; // regenerate this texture
11581 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11582 texture.currentskinframe = skinframe;
11583 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11584 texture.offsetmapping = OFFSETMAPPING_OFF;
11585 texture.offsetscale = 1;
11586 texture.specularscalemod = 1;
11587 texture.specularpowermod = 1;
11589 surface.texture = &texture;
11590 surface.num_triangles = numtriangles;
11591 surface.num_firsttriangle = firsttriangle;
11592 surface.num_vertices = numvertices;
11593 surface.num_firstvertex = firstvertex;
11596 rsurface.texture = R_GetCurrentTexture(surface.texture);
11597 rsurface.lightmaptexture = NULL;
11598 rsurface.deluxemaptexture = NULL;
11599 rsurface.uselightmaptexture = false;
11600 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11603 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)
11605 static msurface_t surface;
11606 const msurface_t *surfacelist = &surface;
11608 // fake enough texture and surface state to render this geometry
11609 surface.texture = texture;
11610 surface.num_triangles = numtriangles;
11611 surface.num_firsttriangle = firsttriangle;
11612 surface.num_vertices = numvertices;
11613 surface.num_firstvertex = firstvertex;
11616 rsurface.texture = R_GetCurrentTexture(surface.texture);
11617 rsurface.lightmaptexture = NULL;
11618 rsurface.deluxemaptexture = NULL;
11619 rsurface.uselightmaptexture = false;
11620 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);