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)"};
209 cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
210 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accordingly, 2: Make it a continuous rotation"};
211 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
212 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
213 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "5", "fake perspective effect for SPR_OVERHEAD sprites"};
214 cvar_t r_overheadsprites_pushback = {CVAR_SAVE, "r_overheadsprites_pushback", "15", "how far to pull the SPR_OVERHEAD sprites toward the eye (used to avoid intersections with 3D models)"};
215 cvar_t r_overheadsprites_scalex = {CVAR_SAVE, "r_overheadsprites_scalex", "1", "additional scale for overhead sprites for x axis"};
216 cvar_t r_overheadsprites_scaley = {CVAR_SAVE, "r_overheadsprites_scaley", "1", "additional scale for overhead sprites for y axis"};
218 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
219 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"};
221 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."};
223 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)"};
225 extern cvar_t v_glslgamma;
227 extern qboolean v_flipped_state;
229 static struct r_bloomstate_s
234 int bloomwidth, bloomheight;
236 textype_t texturetype;
237 int viewfbo; // used to check if r_viewfbo cvar has changed
239 int fbo_framebuffer; // non-zero if r_viewfbo is enabled and working
240 rtexture_t *texture_framebuffercolor; // non-NULL if fbo_screen is non-zero
241 rtexture_t *texture_framebufferdepth; // non-NULL if fbo_screen is non-zero
243 int screentexturewidth, screentextureheight;
244 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
246 int bloomtexturewidth, bloomtextureheight;
247 rtexture_t *texture_bloom;
249 // arrays for rendering the screen passes
250 float screentexcoord2f[8];
251 float bloomtexcoord2f[8];
252 float offsettexcoord2f[8];
254 r_viewport_t viewport;
258 r_waterstate_t r_waterstate;
260 /// shadow volume bsp struct with automatically growing nodes buffer
263 rtexture_t *r_texture_blanknormalmap;
264 rtexture_t *r_texture_white;
265 rtexture_t *r_texture_grey128;
266 rtexture_t *r_texture_black;
267 rtexture_t *r_texture_notexture;
268 rtexture_t *r_texture_whitecube;
269 rtexture_t *r_texture_normalizationcube;
270 rtexture_t *r_texture_fogattenuation;
271 rtexture_t *r_texture_fogheighttexture;
272 rtexture_t *r_texture_gammaramps;
273 unsigned int r_texture_gammaramps_serial;
274 //rtexture_t *r_texture_fogintensity;
275 rtexture_t *r_texture_reflectcube;
277 // TODO: hash lookups?
278 typedef struct cubemapinfo_s
285 int r_texture_numcubemaps;
286 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
288 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
289 unsigned int r_numqueries;
290 unsigned int r_maxqueries;
292 typedef struct r_qwskincache_s
294 char name[MAX_QPATH];
295 skinframe_t *skinframe;
299 static r_qwskincache_t *r_qwskincache;
300 static int r_qwskincache_size;
302 /// vertex coordinates for a quad that covers the screen exactly
303 extern const float r_screenvertex3f[12];
304 extern const float r_d3dscreenvertex3f[12];
305 const float r_screenvertex3f[12] =
312 const float r_d3dscreenvertex3f[12] =
320 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
323 for (i = 0;i < verts;i++)
334 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
337 for (i = 0;i < verts;i++)
347 // FIXME: move this to client?
350 if (gamemode == GAME_NEHAHRA)
352 Cvar_Set("gl_fogenable", "0");
353 Cvar_Set("gl_fogdensity", "0.2");
354 Cvar_Set("gl_fogred", "0.3");
355 Cvar_Set("gl_foggreen", "0.3");
356 Cvar_Set("gl_fogblue", "0.3");
358 r_refdef.fog_density = 0;
359 r_refdef.fog_red = 0;
360 r_refdef.fog_green = 0;
361 r_refdef.fog_blue = 0;
362 r_refdef.fog_alpha = 1;
363 r_refdef.fog_start = 0;
364 r_refdef.fog_end = 16384;
365 r_refdef.fog_height = 1<<30;
366 r_refdef.fog_fadedepth = 128;
367 memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
370 static void R_BuildBlankTextures(void)
372 unsigned char data[4];
373 data[2] = 128; // normal X
374 data[1] = 128; // normal Y
375 data[0] = 255; // normal Z
376 data[3] = 128; // height
377 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
382 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
387 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
392 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
395 static void R_BuildNoTexture(void)
398 unsigned char pix[16][16][4];
399 // this makes a light grey/dark grey checkerboard texture
400 for (y = 0;y < 16;y++)
402 for (x = 0;x < 16;x++)
404 if ((y < 8) ^ (x < 8))
420 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
423 static void R_BuildWhiteCube(void)
425 unsigned char data[6*1*1*4];
426 memset(data, 255, sizeof(data));
427 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
430 static void R_BuildNormalizationCube(void)
434 vec_t s, t, intensity;
437 data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
438 for (side = 0;side < 6;side++)
440 for (y = 0;y < NORMSIZE;y++)
442 for (x = 0;x < NORMSIZE;x++)
444 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
445 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
480 intensity = 127.0f / sqrt(DotProduct(v, v));
481 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
482 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
483 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
484 data[((side*64+y)*64+x)*4+3] = 255;
488 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
492 static void R_BuildFogTexture(void)
496 unsigned char data1[FOGWIDTH][4];
497 //unsigned char data2[FOGWIDTH][4];
500 r_refdef.fogmasktable_start = r_refdef.fog_start;
501 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
502 r_refdef.fogmasktable_range = r_refdef.fogrange;
503 r_refdef.fogmasktable_density = r_refdef.fog_density;
505 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
506 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
508 d = (x * r - r_refdef.fogmasktable_start);
509 if(developer_extra.integer)
510 Con_DPrintf("%f ", d);
512 if (r_fog_exp2.integer)
513 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
515 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
516 if(developer_extra.integer)
517 Con_DPrintf(" : %f ", alpha);
518 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
519 if(developer_extra.integer)
520 Con_DPrintf(" = %f\n", alpha);
521 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
524 for (x = 0;x < FOGWIDTH;x++)
526 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
531 //data2[x][0] = 255 - b;
532 //data2[x][1] = 255 - b;
533 //data2[x][2] = 255 - b;
536 if (r_texture_fogattenuation)
538 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
539 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
543 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
544 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
548 static void R_BuildFogHeightTexture(void)
550 unsigned char *inpixels;
558 strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
559 if (r_refdef.fogheighttexturename[0])
560 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
563 r_refdef.fog_height_tablesize = 0;
564 if (r_texture_fogheighttexture)
565 R_FreeTexture(r_texture_fogheighttexture);
566 r_texture_fogheighttexture = NULL;
567 if (r_refdef.fog_height_table2d)
568 Mem_Free(r_refdef.fog_height_table2d);
569 r_refdef.fog_height_table2d = NULL;
570 if (r_refdef.fog_height_table1d)
571 Mem_Free(r_refdef.fog_height_table1d);
572 r_refdef.fog_height_table1d = NULL;
576 r_refdef.fog_height_tablesize = size;
577 r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
578 r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
579 memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
581 // LordHavoc: now the magic - what is that table2d for? it is a cooked
582 // average fog color table accounting for every fog layer between a point
583 // and the camera. (Note: attenuation is handled separately!)
584 for (y = 0;y < size;y++)
586 for (x = 0;x < size;x++)
592 for (j = x;j <= y;j++)
594 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
600 for (j = x;j >= y;j--)
602 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
607 r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
608 r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
609 r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
610 r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
613 r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
616 //=======================================================================================================================================================
618 static const char *builtinshaderstring =
619 #include "shader_glsl.h"
622 const char *builtinhlslshaderstring =
623 #include "shader_hlsl.h"
626 char *glslshaderstring = NULL;
627 char *hlslshaderstring = NULL;
629 //=======================================================================================================================================================
631 typedef struct shaderpermutationinfo_s
636 shaderpermutationinfo_t;
638 typedef struct shadermodeinfo_s
640 const char *vertexfilename;
641 const char *geometryfilename;
642 const char *fragmentfilename;
648 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
649 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
651 {"#define USEDIFFUSE\n", " diffuse"},
652 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
653 {"#define USEVIEWTINT\n", " viewtint"},
654 {"#define USECOLORMAPPING\n", " colormapping"},
655 {"#define USESATURATION\n", " saturation"},
656 {"#define USEFOGINSIDE\n", " foginside"},
657 {"#define USEFOGOUTSIDE\n", " fogoutside"},
658 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
659 {"#define USEFOGALPHAHACK\n", " fogalphahack"},
660 {"#define USEGAMMARAMPS\n", " gammaramps"},
661 {"#define USECUBEFILTER\n", " cubefilter"},
662 {"#define USEGLOW\n", " glow"},
663 {"#define USEBLOOM\n", " bloom"},
664 {"#define USESPECULAR\n", " specular"},
665 {"#define USEPOSTPROCESSING\n", " postprocessing"},
666 {"#define USEREFLECTION\n", " reflection"},
667 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
668 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
669 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
670 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
671 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
672 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
673 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
674 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
675 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
676 {"#define USEALPHAKILL\n", " alphakill"},
677 {"#define USEREFLECTCUBE\n", " reflectcube"},
678 {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
679 {"#define USEBOUNCEGRID\n", " bouncegrid"},
680 {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
683 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
684 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
686 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
687 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
688 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
689 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
690 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
691 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
692 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
693 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
694 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
695 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
696 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
697 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
698 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
699 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
700 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
701 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
704 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
706 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
707 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
708 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
709 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
710 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
711 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
712 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
713 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
714 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
715 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
716 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
717 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
718 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
719 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
720 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
721 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
724 struct r_glsl_permutation_s;
725 typedef struct r_glsl_permutation_s
728 struct r_glsl_permutation_s *hashnext;
730 unsigned int permutation;
732 /// indicates if we have tried compiling this permutation already
734 /// 0 if compilation failed
736 // texture units assigned to each detected uniform
737 int tex_Texture_First;
738 int tex_Texture_Second;
739 int tex_Texture_GammaRamps;
740 int tex_Texture_Normal;
741 int tex_Texture_Color;
742 int tex_Texture_Gloss;
743 int tex_Texture_Glow;
744 int tex_Texture_SecondaryNormal;
745 int tex_Texture_SecondaryColor;
746 int tex_Texture_SecondaryGloss;
747 int tex_Texture_SecondaryGlow;
748 int tex_Texture_Pants;
749 int tex_Texture_Shirt;
750 int tex_Texture_FogHeightTexture;
751 int tex_Texture_FogMask;
752 int tex_Texture_Lightmap;
753 int tex_Texture_Deluxemap;
754 int tex_Texture_Attenuation;
755 int tex_Texture_Cube;
756 int tex_Texture_Refraction;
757 int tex_Texture_Reflection;
758 int tex_Texture_ShadowMap2D;
759 int tex_Texture_CubeProjection;
760 int tex_Texture_ScreenDepth;
761 int tex_Texture_ScreenNormalMap;
762 int tex_Texture_ScreenDiffuse;
763 int tex_Texture_ScreenSpecular;
764 int tex_Texture_ReflectMask;
765 int tex_Texture_ReflectCube;
766 int tex_Texture_BounceGrid;
767 /// locations of detected uniforms in program object, or -1 if not found
768 int loc_Texture_First;
769 int loc_Texture_Second;
770 int loc_Texture_GammaRamps;
771 int loc_Texture_Normal;
772 int loc_Texture_Color;
773 int loc_Texture_Gloss;
774 int loc_Texture_Glow;
775 int loc_Texture_SecondaryNormal;
776 int loc_Texture_SecondaryColor;
777 int loc_Texture_SecondaryGloss;
778 int loc_Texture_SecondaryGlow;
779 int loc_Texture_Pants;
780 int loc_Texture_Shirt;
781 int loc_Texture_FogHeightTexture;
782 int loc_Texture_FogMask;
783 int loc_Texture_Lightmap;
784 int loc_Texture_Deluxemap;
785 int loc_Texture_Attenuation;
786 int loc_Texture_Cube;
787 int loc_Texture_Refraction;
788 int loc_Texture_Reflection;
789 int loc_Texture_ShadowMap2D;
790 int loc_Texture_CubeProjection;
791 int loc_Texture_ScreenDepth;
792 int loc_Texture_ScreenNormalMap;
793 int loc_Texture_ScreenDiffuse;
794 int loc_Texture_ScreenSpecular;
795 int loc_Texture_ReflectMask;
796 int loc_Texture_ReflectCube;
797 int loc_Texture_BounceGrid;
799 int loc_BloomBlur_Parameters;
801 int loc_Color_Ambient;
802 int loc_Color_Diffuse;
803 int loc_Color_Specular;
807 int loc_DeferredColor_Ambient;
808 int loc_DeferredColor_Diffuse;
809 int loc_DeferredColor_Specular;
810 int loc_DeferredMod_Diffuse;
811 int loc_DeferredMod_Specular;
812 int loc_DistortScaleRefractReflect;
815 int loc_FogHeightFade;
817 int loc_FogPlaneViewDist;
818 int loc_FogRangeRecip;
821 int loc_LightPosition;
822 int loc_OffsetMapping_ScaleSteps;
824 int loc_ReflectColor;
825 int loc_ReflectFactor;
826 int loc_ReflectOffset;
827 int loc_RefractColor;
829 int loc_ScreenCenterRefractReflect;
830 int loc_ScreenScaleRefractReflect;
831 int loc_ScreenToDepth;
832 int loc_ShadowMap_Parameters;
833 int loc_ShadowMap_TextureScale;
834 int loc_SpecularPower;
839 int loc_ViewTintColor;
841 int loc_ModelToLight;
843 int loc_BackgroundTexMatrix;
844 int loc_ModelViewProjectionMatrix;
845 int loc_ModelViewMatrix;
846 int loc_PixelToScreenTexCoord;
847 int loc_ModelToReflectCube;
848 int loc_ShadowMapMatrix;
849 int loc_BloomColorSubtract;
850 int loc_NormalmapScrollBlend;
851 int loc_BounceGridMatrix;
852 int loc_BounceGridIntensity;
854 r_glsl_permutation_t;
856 #define SHADERPERMUTATION_HASHSIZE 256
859 // non-degradable "lightweight" shader parameters to keep the permutations simpler
860 // these can NOT degrade! only use for simple stuff
863 SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
864 SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
865 SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
866 SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
867 SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
868 SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5, ///< postprocess uservec4 is enabled
869 SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6 // use both alpha layers while blending materials, allows more advanced microblending
871 #define SHADERSTATICPARMS_COUNT 7
873 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
874 static int shaderstaticparms_count = 0;
876 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
877 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
878 qboolean R_CompileShader_CheckStaticParms(void)
880 static int r_compileshader_staticparms_save[1];
881 memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
882 memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
885 if (r_glsl_saturation_redcompensate.integer)
886 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
887 if (r_glsl_vertextextureblend_usebothalphas.integer)
888 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
889 if (r_shadow_glossexact.integer)
890 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
891 if (r_glsl_postprocess.integer)
893 if (r_glsl_postprocess_uservec1_enable.integer)
894 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
895 if (r_glsl_postprocess_uservec2_enable.integer)
896 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
897 if (r_glsl_postprocess_uservec3_enable.integer)
898 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
899 if (r_glsl_postprocess_uservec4_enable.integer)
900 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
902 return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
905 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
906 if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
907 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
909 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
910 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
912 shaderstaticparms_count = 0;
915 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
916 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
917 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
918 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
919 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
920 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
921 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
924 /// information about each possible shader permutation
925 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
926 /// currently selected permutation
927 r_glsl_permutation_t *r_glsl_permutation;
928 /// storage for permutations linked in the hash table
929 memexpandablearray_t r_glsl_permutationarray;
931 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
933 //unsigned int hashdepth = 0;
934 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
935 r_glsl_permutation_t *p;
936 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
938 if (p->mode == mode && p->permutation == permutation)
940 //if (hashdepth > 10)
941 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
946 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
948 p->permutation = permutation;
949 p->hashnext = r_glsl_permutationhash[mode][hashindex];
950 r_glsl_permutationhash[mode][hashindex] = p;
951 //if (hashdepth > 10)
952 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
956 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
959 if (!filename || !filename[0])
961 if (!strcmp(filename, "glsl/default.glsl"))
963 if (!glslshaderstring)
965 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
966 if (glslshaderstring)
967 Con_DPrintf("Loading shaders from file %s...\n", filename);
969 glslshaderstring = (char *)builtinshaderstring;
971 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
972 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
975 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
978 if (printfromdisknotice)
979 Con_DPrintf("from disk %s... ", filename);
985 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
989 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
990 char *vertexstring, *geometrystring, *fragmentstring;
991 char permutationname[256];
992 int vertstrings_count = 0;
993 int geomstrings_count = 0;
994 int fragstrings_count = 0;
995 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
996 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
997 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1004 permutationname[0] = 0;
1005 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
1006 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1007 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1009 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1011 // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1012 if(vid.support.gl20shaders130)
1014 vertstrings_list[vertstrings_count++] = "#version 130\n";
1015 geomstrings_list[geomstrings_count++] = "#version 130\n";
1016 fragstrings_list[fragstrings_count++] = "#version 130\n";
1017 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1018 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1019 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1022 // the first pretext is which type of shader to compile as
1023 // (later these will all be bound together as a program object)
1024 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1025 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1026 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1028 // the second pretext is the mode (for example a light source)
1029 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1030 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1031 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1032 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1034 // now add all the permutation pretexts
1035 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1037 if (permutation & (1<<i))
1039 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1040 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1041 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1042 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1046 // keep line numbers correct
1047 vertstrings_list[vertstrings_count++] = "\n";
1048 geomstrings_list[geomstrings_count++] = "\n";
1049 fragstrings_list[fragstrings_count++] = "\n";
1054 R_CompileShader_AddStaticParms(mode, permutation);
1055 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1056 vertstrings_count += shaderstaticparms_count;
1057 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1058 geomstrings_count += shaderstaticparms_count;
1059 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1060 fragstrings_count += shaderstaticparms_count;
1062 // now append the shader text itself
1063 vertstrings_list[vertstrings_count++] = vertexstring;
1064 geomstrings_list[geomstrings_count++] = geometrystring;
1065 fragstrings_list[fragstrings_count++] = fragmentstring;
1067 // if any sources were NULL, clear the respective list
1069 vertstrings_count = 0;
1070 if (!geometrystring)
1071 geomstrings_count = 0;
1072 if (!fragmentstring)
1073 fragstrings_count = 0;
1075 // compile the shader program
1076 if (vertstrings_count + geomstrings_count + fragstrings_count)
1077 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1081 qglUseProgram(p->program);CHECKGLERROR
1082 // look up all the uniform variable names we care about, so we don't
1083 // have to look them up every time we set them
1085 p->loc_Texture_First = qglGetUniformLocation(p->program, "Texture_First");
1086 p->loc_Texture_Second = qglGetUniformLocation(p->program, "Texture_Second");
1087 p->loc_Texture_GammaRamps = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1088 p->loc_Texture_Normal = qglGetUniformLocation(p->program, "Texture_Normal");
1089 p->loc_Texture_Color = qglGetUniformLocation(p->program, "Texture_Color");
1090 p->loc_Texture_Gloss = qglGetUniformLocation(p->program, "Texture_Gloss");
1091 p->loc_Texture_Glow = qglGetUniformLocation(p->program, "Texture_Glow");
1092 p->loc_Texture_SecondaryNormal = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1093 p->loc_Texture_SecondaryColor = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1094 p->loc_Texture_SecondaryGloss = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1095 p->loc_Texture_SecondaryGlow = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1096 p->loc_Texture_Pants = qglGetUniformLocation(p->program, "Texture_Pants");
1097 p->loc_Texture_Shirt = qglGetUniformLocation(p->program, "Texture_Shirt");
1098 p->loc_Texture_FogHeightTexture = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1099 p->loc_Texture_FogMask = qglGetUniformLocation(p->program, "Texture_FogMask");
1100 p->loc_Texture_Lightmap = qglGetUniformLocation(p->program, "Texture_Lightmap");
1101 p->loc_Texture_Deluxemap = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1102 p->loc_Texture_Attenuation = qglGetUniformLocation(p->program, "Texture_Attenuation");
1103 p->loc_Texture_Cube = qglGetUniformLocation(p->program, "Texture_Cube");
1104 p->loc_Texture_Refraction = qglGetUniformLocation(p->program, "Texture_Refraction");
1105 p->loc_Texture_Reflection = qglGetUniformLocation(p->program, "Texture_Reflection");
1106 p->loc_Texture_ShadowMap2D = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1107 p->loc_Texture_CubeProjection = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1108 p->loc_Texture_ScreenDepth = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1109 p->loc_Texture_ScreenNormalMap = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1110 p->loc_Texture_ScreenDiffuse = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1111 p->loc_Texture_ScreenSpecular = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1112 p->loc_Texture_ReflectMask = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1113 p->loc_Texture_ReflectCube = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1114 p->loc_Texture_BounceGrid = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1115 p->loc_Alpha = qglGetUniformLocation(p->program, "Alpha");
1116 p->loc_BloomBlur_Parameters = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1117 p->loc_ClientTime = qglGetUniformLocation(p->program, "ClientTime");
1118 p->loc_Color_Ambient = qglGetUniformLocation(p->program, "Color_Ambient");
1119 p->loc_Color_Diffuse = qglGetUniformLocation(p->program, "Color_Diffuse");
1120 p->loc_Color_Specular = qglGetUniformLocation(p->program, "Color_Specular");
1121 p->loc_Color_Glow = qglGetUniformLocation(p->program, "Color_Glow");
1122 p->loc_Color_Pants = qglGetUniformLocation(p->program, "Color_Pants");
1123 p->loc_Color_Shirt = qglGetUniformLocation(p->program, "Color_Shirt");
1124 p->loc_DeferredColor_Ambient = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1125 p->loc_DeferredColor_Diffuse = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1126 p->loc_DeferredColor_Specular = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1127 p->loc_DeferredMod_Diffuse = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1128 p->loc_DeferredMod_Specular = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1129 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1130 p->loc_EyePosition = qglGetUniformLocation(p->program, "EyePosition");
1131 p->loc_FogColor = qglGetUniformLocation(p->program, "FogColor");
1132 p->loc_FogHeightFade = qglGetUniformLocation(p->program, "FogHeightFade");
1133 p->loc_FogPlane = qglGetUniformLocation(p->program, "FogPlane");
1134 p->loc_FogPlaneViewDist = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1135 p->loc_FogRangeRecip = qglGetUniformLocation(p->program, "FogRangeRecip");
1136 p->loc_LightColor = qglGetUniformLocation(p->program, "LightColor");
1137 p->loc_LightDir = qglGetUniformLocation(p->program, "LightDir");
1138 p->loc_LightPosition = qglGetUniformLocation(p->program, "LightPosition");
1139 p->loc_OffsetMapping_ScaleSteps = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1140 p->loc_PixelSize = qglGetUniformLocation(p->program, "PixelSize");
1141 p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor");
1142 p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor");
1143 p->loc_ReflectOffset = qglGetUniformLocation(p->program, "ReflectOffset");
1144 p->loc_RefractColor = qglGetUniformLocation(p->program, "RefractColor");
1145 p->loc_Saturation = qglGetUniformLocation(p->program, "Saturation");
1146 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1147 p->loc_ScreenScaleRefractReflect = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1148 p->loc_ScreenToDepth = qglGetUniformLocation(p->program, "ScreenToDepth");
1149 p->loc_ShadowMap_Parameters = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1150 p->loc_ShadowMap_TextureScale = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1151 p->loc_SpecularPower = qglGetUniformLocation(p->program, "SpecularPower");
1152 p->loc_UserVec1 = qglGetUniformLocation(p->program, "UserVec1");
1153 p->loc_UserVec2 = qglGetUniformLocation(p->program, "UserVec2");
1154 p->loc_UserVec3 = qglGetUniformLocation(p->program, "UserVec3");
1155 p->loc_UserVec4 = qglGetUniformLocation(p->program, "UserVec4");
1156 p->loc_ViewTintColor = qglGetUniformLocation(p->program, "ViewTintColor");
1157 p->loc_ViewToLight = qglGetUniformLocation(p->program, "ViewToLight");
1158 p->loc_ModelToLight = qglGetUniformLocation(p->program, "ModelToLight");
1159 p->loc_TexMatrix = qglGetUniformLocation(p->program, "TexMatrix");
1160 p->loc_BackgroundTexMatrix = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1161 p->loc_ModelViewMatrix = qglGetUniformLocation(p->program, "ModelViewMatrix");
1162 p->loc_ModelViewProjectionMatrix = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1163 p->loc_PixelToScreenTexCoord = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1164 p->loc_ModelToReflectCube = qglGetUniformLocation(p->program, "ModelToReflectCube");
1165 p->loc_ShadowMapMatrix = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1166 p->loc_BloomColorSubtract = qglGetUniformLocation(p->program, "BloomColorSubtract");
1167 p->loc_NormalmapScrollBlend = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1168 p->loc_BounceGridMatrix = qglGetUniformLocation(p->program, "BounceGridMatrix");
1169 p->loc_BounceGridIntensity = qglGetUniformLocation(p->program, "BounceGridIntensity");
1170 // initialize the samplers to refer to the texture units we use
1171 p->tex_Texture_First = -1;
1172 p->tex_Texture_Second = -1;
1173 p->tex_Texture_GammaRamps = -1;
1174 p->tex_Texture_Normal = -1;
1175 p->tex_Texture_Color = -1;
1176 p->tex_Texture_Gloss = -1;
1177 p->tex_Texture_Glow = -1;
1178 p->tex_Texture_SecondaryNormal = -1;
1179 p->tex_Texture_SecondaryColor = -1;
1180 p->tex_Texture_SecondaryGloss = -1;
1181 p->tex_Texture_SecondaryGlow = -1;
1182 p->tex_Texture_Pants = -1;
1183 p->tex_Texture_Shirt = -1;
1184 p->tex_Texture_FogHeightTexture = -1;
1185 p->tex_Texture_FogMask = -1;
1186 p->tex_Texture_Lightmap = -1;
1187 p->tex_Texture_Deluxemap = -1;
1188 p->tex_Texture_Attenuation = -1;
1189 p->tex_Texture_Cube = -1;
1190 p->tex_Texture_Refraction = -1;
1191 p->tex_Texture_Reflection = -1;
1192 p->tex_Texture_ShadowMap2D = -1;
1193 p->tex_Texture_CubeProjection = -1;
1194 p->tex_Texture_ScreenDepth = -1;
1195 p->tex_Texture_ScreenNormalMap = -1;
1196 p->tex_Texture_ScreenDiffuse = -1;
1197 p->tex_Texture_ScreenSpecular = -1;
1198 p->tex_Texture_ReflectMask = -1;
1199 p->tex_Texture_ReflectCube = -1;
1200 p->tex_Texture_BounceGrid = -1;
1202 if (p->loc_Texture_First >= 0) {p->tex_Texture_First = sampler;qglUniform1i(p->loc_Texture_First , sampler);sampler++;}
1203 if (p->loc_Texture_Second >= 0) {p->tex_Texture_Second = sampler;qglUniform1i(p->loc_Texture_Second , sampler);sampler++;}
1204 if (p->loc_Texture_GammaRamps >= 0) {p->tex_Texture_GammaRamps = sampler;qglUniform1i(p->loc_Texture_GammaRamps , sampler);sampler++;}
1205 if (p->loc_Texture_Normal >= 0) {p->tex_Texture_Normal = sampler;qglUniform1i(p->loc_Texture_Normal , sampler);sampler++;}
1206 if (p->loc_Texture_Color >= 0) {p->tex_Texture_Color = sampler;qglUniform1i(p->loc_Texture_Color , sampler);sampler++;}
1207 if (p->loc_Texture_Gloss >= 0) {p->tex_Texture_Gloss = sampler;qglUniform1i(p->loc_Texture_Gloss , sampler);sampler++;}
1208 if (p->loc_Texture_Glow >= 0) {p->tex_Texture_Glow = sampler;qglUniform1i(p->loc_Texture_Glow , sampler);sampler++;}
1209 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1210 if (p->loc_Texture_SecondaryColor >= 0) {p->tex_Texture_SecondaryColor = sampler;qglUniform1i(p->loc_Texture_SecondaryColor , sampler);sampler++;}
1211 if (p->loc_Texture_SecondaryGloss >= 0) {p->tex_Texture_SecondaryGloss = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss , sampler);sampler++;}
1212 if (p->loc_Texture_SecondaryGlow >= 0) {p->tex_Texture_SecondaryGlow = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow , sampler);sampler++;}
1213 if (p->loc_Texture_Pants >= 0) {p->tex_Texture_Pants = sampler;qglUniform1i(p->loc_Texture_Pants , sampler);sampler++;}
1214 if (p->loc_Texture_Shirt >= 0) {p->tex_Texture_Shirt = sampler;qglUniform1i(p->loc_Texture_Shirt , sampler);sampler++;}
1215 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1216 if (p->loc_Texture_FogMask >= 0) {p->tex_Texture_FogMask = sampler;qglUniform1i(p->loc_Texture_FogMask , sampler);sampler++;}
1217 if (p->loc_Texture_Lightmap >= 0) {p->tex_Texture_Lightmap = sampler;qglUniform1i(p->loc_Texture_Lightmap , sampler);sampler++;}
1218 if (p->loc_Texture_Deluxemap >= 0) {p->tex_Texture_Deluxemap = sampler;qglUniform1i(p->loc_Texture_Deluxemap , sampler);sampler++;}
1219 if (p->loc_Texture_Attenuation >= 0) {p->tex_Texture_Attenuation = sampler;qglUniform1i(p->loc_Texture_Attenuation , sampler);sampler++;}
1220 if (p->loc_Texture_Cube >= 0) {p->tex_Texture_Cube = sampler;qglUniform1i(p->loc_Texture_Cube , sampler);sampler++;}
1221 if (p->loc_Texture_Refraction >= 0) {p->tex_Texture_Refraction = sampler;qglUniform1i(p->loc_Texture_Refraction , sampler);sampler++;}
1222 if (p->loc_Texture_Reflection >= 0) {p->tex_Texture_Reflection = sampler;qglUniform1i(p->loc_Texture_Reflection , sampler);sampler++;}
1223 if (p->loc_Texture_ShadowMap2D >= 0) {p->tex_Texture_ShadowMap2D = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D , sampler);sampler++;}
1224 if (p->loc_Texture_CubeProjection >= 0) {p->tex_Texture_CubeProjection = sampler;qglUniform1i(p->loc_Texture_CubeProjection , sampler);sampler++;}
1225 if (p->loc_Texture_ScreenDepth >= 0) {p->tex_Texture_ScreenDepth = sampler;qglUniform1i(p->loc_Texture_ScreenDepth , sampler);sampler++;}
1226 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1227 if (p->loc_Texture_ScreenDiffuse >= 0) {p->tex_Texture_ScreenDiffuse = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse , sampler);sampler++;}
1228 if (p->loc_Texture_ScreenSpecular >= 0) {p->tex_Texture_ScreenSpecular = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular , sampler);sampler++;}
1229 if (p->loc_Texture_ReflectMask >= 0) {p->tex_Texture_ReflectMask = sampler;qglUniform1i(p->loc_Texture_ReflectMask , sampler);sampler++;}
1230 if (p->loc_Texture_ReflectCube >= 0) {p->tex_Texture_ReflectCube = sampler;qglUniform1i(p->loc_Texture_ReflectCube , sampler);sampler++;}
1231 if (p->loc_Texture_BounceGrid >= 0) {p->tex_Texture_BounceGrid = sampler;qglUniform1i(p->loc_Texture_BounceGrid , sampler);sampler++;}
1233 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1236 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
1240 Mem_Free(vertexstring);
1242 Mem_Free(geometrystring);
1244 Mem_Free(fragmentstring);
1247 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1249 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1250 if (r_glsl_permutation != perm)
1252 r_glsl_permutation = perm;
1253 if (!r_glsl_permutation->program)
1255 if (!r_glsl_permutation->compiled)
1256 R_GLSL_CompilePermutation(perm, mode, permutation);
1257 if (!r_glsl_permutation->program)
1259 // remove features until we find a valid permutation
1261 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1263 // reduce i more quickly whenever it would not remove any bits
1264 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1265 if (!(permutation & j))
1268 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1269 if (!r_glsl_permutation->compiled)
1270 R_GLSL_CompilePermutation(perm, mode, permutation);
1271 if (r_glsl_permutation->program)
1274 if (i >= SHADERPERMUTATION_COUNT)
1276 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1277 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1278 qglUseProgram(0);CHECKGLERROR
1279 return; // no bit left to clear, entire mode is broken
1284 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1286 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1287 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1288 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1295 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1296 extern D3DCAPS9 vid_d3d9caps;
1299 struct r_hlsl_permutation_s;
1300 typedef struct r_hlsl_permutation_s
1302 /// hash lookup data
1303 struct r_hlsl_permutation_s *hashnext;
1305 unsigned int permutation;
1307 /// indicates if we have tried compiling this permutation already
1309 /// NULL if compilation failed
1310 IDirect3DVertexShader9 *vertexshader;
1311 IDirect3DPixelShader9 *pixelshader;
1313 r_hlsl_permutation_t;
1315 typedef enum D3DVSREGISTER_e
1317 D3DVSREGISTER_TexMatrix = 0, // float4x4
1318 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1319 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1320 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1321 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1322 D3DVSREGISTER_ModelToLight = 20, // float4x4
1323 D3DVSREGISTER_EyePosition = 24,
1324 D3DVSREGISTER_FogPlane = 25,
1325 D3DVSREGISTER_LightDir = 26,
1326 D3DVSREGISTER_LightPosition = 27,
1330 typedef enum D3DPSREGISTER_e
1332 D3DPSREGISTER_Alpha = 0,
1333 D3DPSREGISTER_BloomBlur_Parameters = 1,
1334 D3DPSREGISTER_ClientTime = 2,
1335 D3DPSREGISTER_Color_Ambient = 3,
1336 D3DPSREGISTER_Color_Diffuse = 4,
1337 D3DPSREGISTER_Color_Specular = 5,
1338 D3DPSREGISTER_Color_Glow = 6,
1339 D3DPSREGISTER_Color_Pants = 7,
1340 D3DPSREGISTER_Color_Shirt = 8,
1341 D3DPSREGISTER_DeferredColor_Ambient = 9,
1342 D3DPSREGISTER_DeferredColor_Diffuse = 10,
1343 D3DPSREGISTER_DeferredColor_Specular = 11,
1344 D3DPSREGISTER_DeferredMod_Diffuse = 12,
1345 D3DPSREGISTER_DeferredMod_Specular = 13,
1346 D3DPSREGISTER_DistortScaleRefractReflect = 14,
1347 D3DPSREGISTER_EyePosition = 15, // unused
1348 D3DPSREGISTER_FogColor = 16,
1349 D3DPSREGISTER_FogHeightFade = 17,
1350 D3DPSREGISTER_FogPlane = 18,
1351 D3DPSREGISTER_FogPlaneViewDist = 19,
1352 D3DPSREGISTER_FogRangeRecip = 20,
1353 D3DPSREGISTER_LightColor = 21,
1354 D3DPSREGISTER_LightDir = 22, // unused
1355 D3DPSREGISTER_LightPosition = 23,
1356 D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1357 D3DPSREGISTER_PixelSize = 25,
1358 D3DPSREGISTER_ReflectColor = 26,
1359 D3DPSREGISTER_ReflectFactor = 27,
1360 D3DPSREGISTER_ReflectOffset = 28,
1361 D3DPSREGISTER_RefractColor = 29,
1362 D3DPSREGISTER_Saturation = 30,
1363 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1364 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1365 D3DPSREGISTER_ScreenToDepth = 33,
1366 D3DPSREGISTER_ShadowMap_Parameters = 34,
1367 D3DPSREGISTER_ShadowMap_TextureScale = 35,
1368 D3DPSREGISTER_SpecularPower = 36,
1369 D3DPSREGISTER_UserVec1 = 37,
1370 D3DPSREGISTER_UserVec2 = 38,
1371 D3DPSREGISTER_UserVec3 = 39,
1372 D3DPSREGISTER_UserVec4 = 40,
1373 D3DPSREGISTER_ViewTintColor = 41,
1374 D3DPSREGISTER_PixelToScreenTexCoord = 42,
1375 D3DPSREGISTER_BloomColorSubtract = 43,
1376 D3DPSREGISTER_ViewToLight = 44, // float4x4
1377 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1378 D3DPSREGISTER_NormalmapScrollBlend = 52,
1383 /// information about each possible shader permutation
1384 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1385 /// currently selected permutation
1386 r_hlsl_permutation_t *r_hlsl_permutation;
1387 /// storage for permutations linked in the hash table
1388 memexpandablearray_t r_hlsl_permutationarray;
1390 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1392 //unsigned int hashdepth = 0;
1393 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1394 r_hlsl_permutation_t *p;
1395 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1397 if (p->mode == mode && p->permutation == permutation)
1399 //if (hashdepth > 10)
1400 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1405 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1407 p->permutation = permutation;
1408 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1409 r_hlsl_permutationhash[mode][hashindex] = p;
1410 //if (hashdepth > 10)
1411 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1415 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1418 if (!filename || !filename[0])
1420 if (!strcmp(filename, "hlsl/default.hlsl"))
1422 if (!hlslshaderstring)
1424 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1425 if (hlslshaderstring)
1426 Con_DPrintf("Loading shaders from file %s...\n", filename);
1428 hlslshaderstring = (char *)builtinhlslshaderstring;
1430 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1431 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1432 return shaderstring;
1434 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1437 if (printfromdisknotice)
1438 Con_DPrintf("from disk %s... ", filename);
1439 return shaderstring;
1441 return shaderstring;
1445 //#include <d3dx9shader.h>
1446 //#include <d3dx9mesh.h>
1448 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1450 DWORD *vsbin = NULL;
1451 DWORD *psbin = NULL;
1452 fs_offset_t vsbinsize;
1453 fs_offset_t psbinsize;
1454 // IDirect3DVertexShader9 *vs = NULL;
1455 // IDirect3DPixelShader9 *ps = NULL;
1456 ID3DXBuffer *vslog = NULL;
1457 ID3DXBuffer *vsbuffer = NULL;
1458 ID3DXConstantTable *vsconstanttable = NULL;
1459 ID3DXBuffer *pslog = NULL;
1460 ID3DXBuffer *psbuffer = NULL;
1461 ID3DXConstantTable *psconstanttable = NULL;
1464 char temp[MAX_INPUTLINE];
1465 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1466 qboolean debugshader = gl_paranoid.integer != 0;
1467 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1468 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1471 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1472 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1474 if ((!vsbin && vertstring) || (!psbin && fragstring))
1476 const char* dllnames_d3dx9 [] =
1500 dllhandle_t d3dx9_dll = NULL;
1501 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1502 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1503 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1504 dllfunction_t d3dx9_dllfuncs[] =
1506 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
1507 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
1508 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
1511 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1513 DWORD shaderflags = 0;
1515 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1516 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1517 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1518 if (vertstring && vertstring[0])
1522 // vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1523 // FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1524 FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1525 vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1528 vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1531 vsbinsize = vsbuffer->GetBufferSize();
1532 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1533 memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1534 vsbuffer->Release();
1538 strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1539 Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1543 if (fragstring && fragstring[0])
1547 // psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1548 // FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1549 FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1550 psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1553 psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1556 psbinsize = psbuffer->GetBufferSize();
1557 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1558 memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1559 psbuffer->Release();
1563 strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1564 Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1568 Sys_UnloadLibrary(&d3dx9_dll);
1571 Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1575 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1576 if (FAILED(vsresult))
1577 Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1578 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1579 if (FAILED(psresult))
1580 Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1582 // free the shader data
1583 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1584 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1587 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1590 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1591 int vertstring_length = 0;
1592 int geomstring_length = 0;
1593 int fragstring_length = 0;
1595 char *vertexstring, *geometrystring, *fragmentstring;
1596 char *vertstring, *geomstring, *fragstring;
1597 char permutationname[256];
1598 char cachename[256];
1599 int vertstrings_count = 0;
1600 int geomstrings_count = 0;
1601 int fragstrings_count = 0;
1602 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1603 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1604 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1609 p->vertexshader = NULL;
1610 p->pixelshader = NULL;
1612 permutationname[0] = 0;
1614 vertexstring = R_HLSL_GetText(modeinfo->vertexfilename, true);
1615 geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1616 fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1618 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1619 strlcat(cachename, "hlsl/", sizeof(cachename));
1621 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1622 vertstrings_count = 0;
1623 geomstrings_count = 0;
1624 fragstrings_count = 0;
1625 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1626 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1627 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1629 // the first pretext is which type of shader to compile as
1630 // (later these will all be bound together as a program object)
1631 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1632 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1633 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1635 // the second pretext is the mode (for example a light source)
1636 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1637 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1638 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1639 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1640 strlcat(cachename, modeinfo->name, sizeof(cachename));
1642 // now add all the permutation pretexts
1643 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1645 if (permutation & (1<<i))
1647 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1648 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1649 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1650 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1651 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1655 // keep line numbers correct
1656 vertstrings_list[vertstrings_count++] = "\n";
1657 geomstrings_list[geomstrings_count++] = "\n";
1658 fragstrings_list[fragstrings_count++] = "\n";
1663 R_CompileShader_AddStaticParms(mode, permutation);
1664 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1665 vertstrings_count += shaderstaticparms_count;
1666 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1667 geomstrings_count += shaderstaticparms_count;
1668 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1669 fragstrings_count += shaderstaticparms_count;
1671 // replace spaces in the cachename with _ characters
1672 for (i = 0;cachename[i];i++)
1673 if (cachename[i] == ' ')
1676 // now append the shader text itself
1677 vertstrings_list[vertstrings_count++] = vertexstring;
1678 geomstrings_list[geomstrings_count++] = geometrystring;
1679 fragstrings_list[fragstrings_count++] = fragmentstring;
1681 // if any sources were NULL, clear the respective list
1683 vertstrings_count = 0;
1684 if (!geometrystring)
1685 geomstrings_count = 0;
1686 if (!fragmentstring)
1687 fragstrings_count = 0;
1689 vertstring_length = 0;
1690 for (i = 0;i < vertstrings_count;i++)
1691 vertstring_length += strlen(vertstrings_list[i]);
1692 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1693 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1694 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1696 geomstring_length = 0;
1697 for (i = 0;i < geomstrings_count;i++)
1698 geomstring_length += strlen(geomstrings_list[i]);
1699 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1700 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1701 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1703 fragstring_length = 0;
1704 for (i = 0;i < fragstrings_count;i++)
1705 fragstring_length += strlen(fragstrings_list[i]);
1706 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1707 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1708 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1710 // try to load the cached shader, or generate one
1711 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1713 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1714 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1716 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
1720 Mem_Free(vertstring);
1722 Mem_Free(geomstring);
1724 Mem_Free(fragstring);
1726 Mem_Free(vertexstring);
1728 Mem_Free(geometrystring);
1730 Mem_Free(fragmentstring);
1733 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1734 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1735 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);}
1736 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);}
1737 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);}
1738 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);}
1740 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1741 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1742 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);}
1743 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);}
1744 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);}
1745 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);}
1747 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1749 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1750 if (r_hlsl_permutation != perm)
1752 r_hlsl_permutation = perm;
1753 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1755 if (!r_hlsl_permutation->compiled)
1756 R_HLSL_CompilePermutation(perm, mode, permutation);
1757 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1759 // remove features until we find a valid permutation
1761 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1763 // reduce i more quickly whenever it would not remove any bits
1764 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1765 if (!(permutation & j))
1768 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1769 if (!r_hlsl_permutation->compiled)
1770 R_HLSL_CompilePermutation(perm, mode, permutation);
1771 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1774 if (i >= SHADERPERMUTATION_COUNT)
1776 //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1777 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1778 return; // no bit left to clear, entire mode is broken
1782 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1783 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1785 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1786 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1787 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1791 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1793 DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1794 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1795 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1796 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1799 void R_GLSL_Restart_f(void)
1801 unsigned int i, limit;
1802 if (glslshaderstring && glslshaderstring != builtinshaderstring)
1803 Mem_Free(glslshaderstring);
1804 glslshaderstring = NULL;
1805 if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1806 Mem_Free(hlslshaderstring);
1807 hlslshaderstring = NULL;
1808 switch(vid.renderpath)
1810 case RENDERPATH_D3D9:
1813 r_hlsl_permutation_t *p;
1814 r_hlsl_permutation = NULL;
1815 limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1816 for (i = 0;i < limit;i++)
1818 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1820 if (p->vertexshader)
1821 IDirect3DVertexShader9_Release(p->vertexshader);
1823 IDirect3DPixelShader9_Release(p->pixelshader);
1824 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1827 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1831 case RENDERPATH_D3D10:
1832 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1834 case RENDERPATH_D3D11:
1835 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1837 case RENDERPATH_GL20:
1838 case RENDERPATH_GLES2:
1840 r_glsl_permutation_t *p;
1841 r_glsl_permutation = NULL;
1842 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1843 for (i = 0;i < limit;i++)
1845 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1847 GL_Backend_FreeProgram(p->program);
1848 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1851 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1854 case RENDERPATH_GL11:
1855 case RENDERPATH_GL13:
1856 case RENDERPATH_GLES1:
1858 case RENDERPATH_SOFT:
1863 void R_GLSL_DumpShader_f(void)
1868 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1871 FS_Print(file, "/* The engine may define the following macros:\n");
1872 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1873 for (i = 0;i < SHADERMODE_COUNT;i++)
1874 FS_Print(file, glslshadermodeinfo[i].pretext);
1875 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1876 FS_Print(file, shaderpermutationinfo[i].pretext);
1877 FS_Print(file, "*/\n");
1878 FS_Print(file, builtinshaderstring);
1880 Con_Printf("glsl/default.glsl written\n");
1883 Con_Printf("failed to write to glsl/default.glsl\n");
1885 file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1888 FS_Print(file, "/* The engine may define the following macros:\n");
1889 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1890 for (i = 0;i < SHADERMODE_COUNT;i++)
1891 FS_Print(file, hlslshadermodeinfo[i].pretext);
1892 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1893 FS_Print(file, shaderpermutationinfo[i].pretext);
1894 FS_Print(file, "*/\n");
1895 FS_Print(file, builtinhlslshaderstring);
1897 Con_Printf("hlsl/default.hlsl written\n");
1900 Con_Printf("failed to write to hlsl/default.hlsl\n");
1903 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
1906 texturemode = GL_MODULATE;
1907 switch (vid.renderpath)
1909 case RENDERPATH_D3D9:
1911 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))));
1912 R_Mesh_TexBind(GL20TU_FIRST , first );
1913 R_Mesh_TexBind(GL20TU_SECOND, second);
1916 case RENDERPATH_D3D10:
1917 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1919 case RENDERPATH_D3D11:
1920 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1922 case RENDERPATH_GL20:
1923 case RENDERPATH_GLES2:
1924 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))));
1925 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1926 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1928 case RENDERPATH_GL13:
1929 case RENDERPATH_GLES1:
1930 R_Mesh_TexBind(0, first );
1931 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1932 R_Mesh_TexBind(1, second);
1934 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1936 case RENDERPATH_GL11:
1937 R_Mesh_TexBind(0, first );
1939 case RENDERPATH_SOFT:
1940 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))));
1941 R_Mesh_TexBind(GL20TU_FIRST , first );
1942 R_Mesh_TexBind(GL20TU_SECOND, second);
1947 void R_SetupShader_DepthOrShadow(void)
1949 switch (vid.renderpath)
1951 case RENDERPATH_D3D9:
1953 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1956 case RENDERPATH_D3D10:
1957 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1959 case RENDERPATH_D3D11:
1960 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1962 case RENDERPATH_GL20:
1963 case RENDERPATH_GLES2:
1964 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1966 case RENDERPATH_GL13:
1967 case RENDERPATH_GLES1:
1968 R_Mesh_TexBind(0, 0);
1969 R_Mesh_TexBind(1, 0);
1971 case RENDERPATH_GL11:
1972 R_Mesh_TexBind(0, 0);
1974 case RENDERPATH_SOFT:
1975 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
1980 void R_SetupShader_ShowDepth(void)
1982 switch (vid.renderpath)
1984 case RENDERPATH_D3D9:
1986 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
1989 case RENDERPATH_D3D10:
1990 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1992 case RENDERPATH_D3D11:
1993 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1995 case RENDERPATH_GL20:
1996 case RENDERPATH_GLES2:
1997 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
1999 case RENDERPATH_GL13:
2000 case RENDERPATH_GLES1:
2002 case RENDERPATH_GL11:
2004 case RENDERPATH_SOFT:
2005 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
2010 extern qboolean r_shadow_usingdeferredprepass;
2011 extern cvar_t r_shadow_deferred_8bitrange;
2012 extern rtexture_t *r_shadow_attenuationgradienttexture;
2013 extern rtexture_t *r_shadow_attenuation2dtexture;
2014 extern rtexture_t *r_shadow_attenuation3dtexture;
2015 extern qboolean r_shadow_usingshadowmap2d;
2016 extern qboolean r_shadow_usingshadowmaportho;
2017 extern float r_shadow_shadowmap_texturescale[2];
2018 extern float r_shadow_shadowmap_parameters[4];
2019 extern qboolean r_shadow_shadowmapvsdct;
2020 extern qboolean r_shadow_shadowmapsampler;
2021 extern int r_shadow_shadowmappcf;
2022 extern rtexture_t *r_shadow_shadowmap2dtexture;
2023 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2024 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2025 extern matrix4x4_t r_shadow_shadowmapmatrix;
2026 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2027 extern int r_shadow_prepass_width;
2028 extern int r_shadow_prepass_height;
2029 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2030 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2031 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2032 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2033 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2035 #define BLENDFUNC_ALLOWS_COLORMOD 1
2036 #define BLENDFUNC_ALLOWS_FOG 2
2037 #define BLENDFUNC_ALLOWS_FOG_HACK0 4
2038 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2039 #define BLENDFUNC_ALLOWS_ANYFOG (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2040 static int R_BlendFuncFlags(int src, int dst)
2044 // a blendfunc allows colormod if:
2045 // a) it can never keep the destination pixel invariant, or
2046 // b) it can keep the destination pixel invariant, and still can do so if colormodded
2047 // this is to prevent unintended side effects from colormod
2049 // a blendfunc allows fog if:
2050 // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2051 // this is to prevent unintended side effects from fog
2053 // these checks are the output of fogeval.pl
2055 r |= BLENDFUNC_ALLOWS_COLORMOD;
2056 if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2057 if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2058 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2059 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2060 if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2061 if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2062 if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2063 if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2064 if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2065 if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2066 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2067 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2068 if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2069 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2070 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2071 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2072 if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2073 if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2074 if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2075 if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2076 if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2081 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)
2083 // select a permutation of the lighting shader appropriate to this
2084 // combination of texture, entity, light source, and fogging, only use the
2085 // minimum features necessary to avoid wasting rendering time in the
2086 // fragment shader on features that are not being used
2087 unsigned int permutation = 0;
2088 unsigned int mode = 0;
2090 static float dummy_colormod[3] = {1, 1, 1};
2091 float *colormod = rsurface.colormod;
2093 matrix4x4_t tempmatrix;
2094 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2095 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2096 permutation |= SHADERPERMUTATION_ALPHAKILL;
2097 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2098 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2099 if (rsurfacepass == RSURFPASS_BACKGROUND)
2101 // distorted background
2102 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2104 mode = SHADERMODE_WATER;
2105 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2107 // this is the right thing to do for wateralpha
2108 GL_BlendFunc(GL_ONE, GL_ZERO);
2109 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2113 // this is the right thing to do for entity alpha
2114 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2115 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2118 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2120 mode = SHADERMODE_REFRACTION;
2121 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2122 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2126 mode = SHADERMODE_GENERIC;
2127 permutation |= SHADERPERMUTATION_DIFFUSE;
2128 GL_BlendFunc(GL_ONE, GL_ZERO);
2129 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2132 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2134 if (r_glsl_offsetmapping.integer)
2136 switch(rsurface.texture->offsetmapping)
2138 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2139 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2140 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2141 case OFFSETMAPPING_OFF: break;
2144 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2145 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2146 // normalmap (deferred prepass), may use alpha test on diffuse
2147 mode = SHADERMODE_DEFERREDGEOMETRY;
2148 GL_BlendFunc(GL_ONE, GL_ZERO);
2149 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2151 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2153 if (r_glsl_offsetmapping.integer)
2155 switch(rsurface.texture->offsetmapping)
2157 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2158 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2159 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2160 case OFFSETMAPPING_OFF: break;
2163 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2164 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2166 mode = SHADERMODE_LIGHTSOURCE;
2167 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2168 permutation |= SHADERPERMUTATION_CUBEFILTER;
2169 if (diffusescale > 0)
2170 permutation |= SHADERPERMUTATION_DIFFUSE;
2171 if (specularscale > 0)
2172 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2173 if (r_refdef.fogenabled)
2174 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2175 if (rsurface.texture->colormapping)
2176 permutation |= SHADERPERMUTATION_COLORMAPPING;
2177 if (r_shadow_usingshadowmap2d)
2179 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2180 if(r_shadow_shadowmapvsdct)
2181 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2183 if (r_shadow_shadowmapsampler)
2184 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2185 if (r_shadow_shadowmappcf > 1)
2186 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2187 else if (r_shadow_shadowmappcf)
2188 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2190 if (rsurface.texture->reflectmasktexture)
2191 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2192 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2193 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2195 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2197 if (r_glsl_offsetmapping.integer)
2199 switch(rsurface.texture->offsetmapping)
2201 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2202 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2203 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2204 case OFFSETMAPPING_OFF: break;
2207 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2208 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2209 // unshaded geometry (fullbright or ambient model lighting)
2210 mode = SHADERMODE_FLATCOLOR;
2211 ambientscale = diffusescale = specularscale = 0;
2212 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2213 permutation |= SHADERPERMUTATION_GLOW;
2214 if (r_refdef.fogenabled)
2215 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2216 if (rsurface.texture->colormapping)
2217 permutation |= SHADERPERMUTATION_COLORMAPPING;
2218 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2220 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2221 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2223 if (r_shadow_shadowmapsampler)
2224 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2225 if (r_shadow_shadowmappcf > 1)
2226 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2227 else if (r_shadow_shadowmappcf)
2228 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2230 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2231 permutation |= SHADERPERMUTATION_REFLECTION;
2232 if (rsurface.texture->reflectmasktexture)
2233 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2234 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2235 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2237 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2239 if (r_glsl_offsetmapping.integer)
2241 switch(rsurface.texture->offsetmapping)
2243 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2244 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2245 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2246 case OFFSETMAPPING_OFF: break;
2249 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2250 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2251 // directional model lighting
2252 mode = SHADERMODE_LIGHTDIRECTION;
2253 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2254 permutation |= SHADERPERMUTATION_GLOW;
2255 permutation |= SHADERPERMUTATION_DIFFUSE;
2256 if (specularscale > 0)
2257 permutation |= SHADERPERMUTATION_SPECULAR;
2258 if (r_refdef.fogenabled)
2259 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2260 if (rsurface.texture->colormapping)
2261 permutation |= SHADERPERMUTATION_COLORMAPPING;
2262 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2264 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2265 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2267 if (r_shadow_shadowmapsampler)
2268 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2269 if (r_shadow_shadowmappcf > 1)
2270 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2271 else if (r_shadow_shadowmappcf)
2272 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2274 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2275 permutation |= SHADERPERMUTATION_REFLECTION;
2276 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2277 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2278 if (rsurface.texture->reflectmasktexture)
2279 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2280 if (r_shadow_bouncegridtexture)
2282 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2283 if (r_shadow_bouncegriddirectional)
2284 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2286 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2287 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2289 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2291 if (r_glsl_offsetmapping.integer)
2293 switch(rsurface.texture->offsetmapping)
2295 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2296 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2297 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2298 case OFFSETMAPPING_OFF: break;
2301 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2302 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2303 // ambient model lighting
2304 mode = SHADERMODE_LIGHTDIRECTION;
2305 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2306 permutation |= SHADERPERMUTATION_GLOW;
2307 if (r_refdef.fogenabled)
2308 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2309 if (rsurface.texture->colormapping)
2310 permutation |= SHADERPERMUTATION_COLORMAPPING;
2311 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2313 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2314 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2316 if (r_shadow_shadowmapsampler)
2317 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2318 if (r_shadow_shadowmappcf > 1)
2319 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2320 else if (r_shadow_shadowmappcf)
2321 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2323 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2324 permutation |= SHADERPERMUTATION_REFLECTION;
2325 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2326 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2327 if (rsurface.texture->reflectmasktexture)
2328 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2329 if (r_shadow_bouncegridtexture)
2331 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2332 if (r_shadow_bouncegriddirectional)
2333 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2335 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2336 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2340 if (r_glsl_offsetmapping.integer)
2342 switch(rsurface.texture->offsetmapping)
2344 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2345 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2346 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2347 case OFFSETMAPPING_OFF: break;
2350 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2351 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2353 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2354 permutation |= SHADERPERMUTATION_GLOW;
2355 if (r_refdef.fogenabled)
2356 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2357 if (rsurface.texture->colormapping)
2358 permutation |= SHADERPERMUTATION_COLORMAPPING;
2359 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2361 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2362 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2364 if (r_shadow_shadowmapsampler)
2365 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2366 if (r_shadow_shadowmappcf > 1)
2367 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2368 else if (r_shadow_shadowmappcf)
2369 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2371 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2372 permutation |= SHADERPERMUTATION_REFLECTION;
2373 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2374 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2375 if (rsurface.texture->reflectmasktexture)
2376 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2377 if (FAKELIGHT_ENABLED)
2379 // fake lightmapping (q1bsp, q3bsp, fullbright map)
2380 mode = SHADERMODE_FAKELIGHT;
2381 permutation |= SHADERPERMUTATION_DIFFUSE;
2382 if (specularscale > 0)
2383 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2385 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2387 // deluxemapping (light direction texture)
2388 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2389 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2391 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2392 permutation |= SHADERPERMUTATION_DIFFUSE;
2393 if (specularscale > 0)
2394 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2396 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2398 // fake deluxemapping (uniform light direction in tangentspace)
2399 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2400 permutation |= SHADERPERMUTATION_DIFFUSE;
2401 if (specularscale > 0)
2402 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2404 else if (rsurface.uselightmaptexture)
2406 // ordinary lightmapping (q1bsp, q3bsp)
2407 mode = SHADERMODE_LIGHTMAP;
2411 // ordinary vertex coloring (q3bsp)
2412 mode = SHADERMODE_VERTEXCOLOR;
2414 if (r_shadow_bouncegridtexture)
2416 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2417 if (r_shadow_bouncegriddirectional)
2418 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2420 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2421 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2423 if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2424 colormod = dummy_colormod;
2425 if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2426 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2427 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2428 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2429 switch(vid.renderpath)
2431 case RENDERPATH_D3D9:
2433 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);
2434 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2435 R_SetupShader_SetPermutationHLSL(mode, permutation);
2436 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2437 if (mode == SHADERMODE_LIGHTSOURCE)
2439 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2440 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2444 if (mode == SHADERMODE_LIGHTDIRECTION)
2446 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2449 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2450 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2451 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2452 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2453 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2455 if (mode == SHADERMODE_LIGHTSOURCE)
2457 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2458 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2459 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2460 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2461 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2463 // additive passes are only darkened by fog, not tinted
2464 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2465 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2469 if (mode == SHADERMODE_FLATCOLOR)
2471 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2473 else if (mode == SHADERMODE_LIGHTDIRECTION)
2475 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]);
2476 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2477 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);
2478 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);
2479 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2480 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2481 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2485 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2486 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2487 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);
2488 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);
2489 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2491 // additive passes are only darkened by fog, not tinted
2492 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2493 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2495 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2496 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);
2497 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2498 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2499 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2500 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2501 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2502 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2503 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2504 if (mode == SHADERMODE_WATER)
2505 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2507 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2508 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2509 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2510 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));
2511 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2512 if (rsurface.texture->pantstexture)
2513 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2515 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2516 if (rsurface.texture->shirttexture)
2517 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2519 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2520 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2521 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2522 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2523 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2524 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2525 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2526 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2527 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2528 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2530 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2531 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2533 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2534 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2535 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2536 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2537 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2538 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2539 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2540 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2541 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2542 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2543 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2544 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2545 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2546 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2547 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2548 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2549 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2550 if (rsurfacepass == RSURFPASS_BACKGROUND)
2552 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2553 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2554 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2558 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2560 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2561 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2562 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2563 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2564 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2566 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2567 if (rsurface.rtlight)
2569 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2570 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2575 case RENDERPATH_D3D10:
2576 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2578 case RENDERPATH_D3D11:
2579 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2581 case RENDERPATH_GL20:
2582 case RENDERPATH_GLES2:
2583 if (!vid.useinterleavedarrays)
2585 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);
2586 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2587 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2588 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2589 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2590 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2591 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2592 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2596 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);
2597 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2599 R_SetupShader_SetPermutationGLSL(mode, permutation);
2600 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2601 if (mode == SHADERMODE_LIGHTSOURCE)
2603 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2604 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2605 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2606 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2607 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2608 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);
2610 // additive passes are only darkened by fog, not tinted
2611 if (r_glsl_permutation->loc_FogColor >= 0)
2612 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2613 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2617 if (mode == SHADERMODE_FLATCOLOR)
2619 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2621 else if (mode == SHADERMODE_LIGHTDIRECTION)
2623 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]);
2624 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]);
2625 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);
2626 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);
2627 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);
2628 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]);
2629 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]);
2633 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]);
2634 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]);
2635 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);
2636 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);
2637 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);
2639 // additive passes are only darkened by fog, not tinted
2640 if (r_glsl_permutation->loc_FogColor >= 0)
2642 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2643 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2645 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2647 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);
2648 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]);
2649 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]);
2650 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]);
2651 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]);
2652 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2653 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2654 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2655 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]);
2657 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2658 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2659 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2660 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]);
2661 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]);
2663 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2664 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));
2665 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2666 if (r_glsl_permutation->loc_Color_Pants >= 0)
2668 if (rsurface.texture->pantstexture)
2669 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2671 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2673 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2675 if (rsurface.texture->shirttexture)
2676 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2678 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2680 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]);
2681 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2682 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2683 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2684 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2685 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2686 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2687 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2688 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2690 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]);
2691 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2692 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);}
2693 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2695 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
2696 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
2697 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
2698 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
2699 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
2700 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
2701 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
2702 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
2703 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
2704 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
2705 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
2706 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
2707 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
2708 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
2709 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);
2710 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
2711 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
2712 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2713 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2714 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2715 if (rsurfacepass == RSURFPASS_BACKGROUND)
2717 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);
2718 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);
2719 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);
2723 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);
2725 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2726 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2727 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
2728 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
2729 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2731 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture );
2732 if (rsurface.rtlight)
2734 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2735 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2738 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2741 case RENDERPATH_GL11:
2742 case RENDERPATH_GL13:
2743 case RENDERPATH_GLES1:
2745 case RENDERPATH_SOFT:
2746 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);
2747 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2748 R_SetupShader_SetPermutationSoft(mode, permutation);
2749 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2750 if (mode == SHADERMODE_LIGHTSOURCE)
2752 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2753 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2754 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2755 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2756 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2757 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2759 // additive passes are only darkened by fog, not tinted
2760 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2761 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2765 if (mode == SHADERMODE_FLATCOLOR)
2767 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2769 else if (mode == SHADERMODE_LIGHTDIRECTION)
2771 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]);
2772 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2773 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);
2774 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);
2775 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2776 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]);
2777 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2781 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2782 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2783 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);
2784 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);
2785 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2787 // additive passes are only darkened by fog, not tinted
2788 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2789 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2791 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2792 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);
2793 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2794 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2795 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]);
2796 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]);
2797 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2798 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2799 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2800 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2802 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2803 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2804 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2805 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2806 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]);
2808 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2809 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));
2810 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2811 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2813 if (rsurface.texture->pantstexture)
2814 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2816 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2818 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2820 if (rsurface.texture->shirttexture)
2821 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2823 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2825 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2826 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2827 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2828 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2829 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2830 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2831 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2832 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2833 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2835 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2836 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2838 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2839 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2840 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2841 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2842 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2843 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2844 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2845 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2846 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2847 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2848 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2849 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2850 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2851 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2852 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2853 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2854 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2855 if (rsurfacepass == RSURFPASS_BACKGROUND)
2857 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2858 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2859 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2863 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2865 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2866 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2867 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2868 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2869 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2871 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2872 if (rsurface.rtlight)
2874 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2875 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2882 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2884 // select a permutation of the lighting shader appropriate to this
2885 // combination of texture, entity, light source, and fogging, only use the
2886 // minimum features necessary to avoid wasting rendering time in the
2887 // fragment shader on features that are not being used
2888 unsigned int permutation = 0;
2889 unsigned int mode = 0;
2890 const float *lightcolorbase = rtlight->currentcolor;
2891 float ambientscale = rtlight->ambientscale;
2892 float diffusescale = rtlight->diffusescale;
2893 float specularscale = rtlight->specularscale;
2894 // this is the location of the light in view space
2895 vec3_t viewlightorigin;
2896 // this transforms from view space (camera) to light space (cubemap)
2897 matrix4x4_t viewtolight;
2898 matrix4x4_t lighttoview;
2899 float viewtolight16f[16];
2900 float range = 1.0f / r_shadow_deferred_8bitrange.value;
2902 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2903 if (rtlight->currentcubemap != r_texture_whitecube)
2904 permutation |= SHADERPERMUTATION_CUBEFILTER;
2905 if (diffusescale > 0)
2906 permutation |= SHADERPERMUTATION_DIFFUSE;
2907 if (specularscale > 0 && r_shadow_gloss.integer > 0)
2908 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2909 if (r_shadow_usingshadowmap2d)
2911 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2912 if (r_shadow_shadowmapvsdct)
2913 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2915 if (r_shadow_shadowmapsampler)
2916 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2917 if (r_shadow_shadowmappcf > 1)
2918 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2919 else if (r_shadow_shadowmappcf)
2920 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2922 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2923 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2924 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2925 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2926 switch(vid.renderpath)
2928 case RENDERPATH_D3D9:
2930 R_SetupShader_SetPermutationHLSL(mode, permutation);
2931 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2932 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
2933 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2934 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2935 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2936 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2937 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2938 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2939 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2940 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2942 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2943 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthcolortexture );
2944 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2945 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2946 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dcolortexture );
2947 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2950 case RENDERPATH_D3D10:
2951 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2953 case RENDERPATH_D3D11:
2954 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2956 case RENDERPATH_GL20:
2957 case RENDERPATH_GLES2:
2958 R_SetupShader_SetPermutationGLSL(mode, permutation);
2959 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2960 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
2961 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);
2962 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);
2963 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);
2964 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]);
2965 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]);
2966 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));
2967 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]);
2968 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
2970 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2971 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2972 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2973 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2974 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );
2975 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2977 case RENDERPATH_GL11:
2978 case RENDERPATH_GL13:
2979 case RENDERPATH_GLES1:
2981 case RENDERPATH_SOFT:
2982 R_SetupShader_SetPermutationGLSL(mode, permutation);
2983 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2984 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
2985 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2986 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2987 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2988 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2989 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]);
2990 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));
2991 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2992 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2994 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2995 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2996 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2997 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2998 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
2999 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3004 #define SKINFRAME_HASH 1024
3008 int loadsequence; // incremented each level change
3009 memexpandablearray_t array;
3010 skinframe_t *hash[SKINFRAME_HASH];
3013 r_skinframe_t r_skinframe;
3015 void R_SkinFrame_PrepareForPurge(void)
3017 r_skinframe.loadsequence++;
3018 // wrap it without hitting zero
3019 if (r_skinframe.loadsequence >= 200)
3020 r_skinframe.loadsequence = 1;
3023 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3027 // mark the skinframe as used for the purging code
3028 skinframe->loadsequence = r_skinframe.loadsequence;
3031 void R_SkinFrame_Purge(void)
3035 for (i = 0;i < SKINFRAME_HASH;i++)
3037 for (s = r_skinframe.hash[i];s;s = s->next)
3039 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3041 if (s->merged == s->base)
3043 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3044 R_PurgeTexture(s->stain );s->stain = NULL;
3045 R_PurgeTexture(s->merged);s->merged = NULL;
3046 R_PurgeTexture(s->base );s->base = NULL;
3047 R_PurgeTexture(s->pants );s->pants = NULL;
3048 R_PurgeTexture(s->shirt );s->shirt = NULL;
3049 R_PurgeTexture(s->nmap );s->nmap = NULL;
3050 R_PurgeTexture(s->gloss );s->gloss = NULL;
3051 R_PurgeTexture(s->glow );s->glow = NULL;
3052 R_PurgeTexture(s->fog );s->fog = NULL;
3053 R_PurgeTexture(s->reflect);s->reflect = NULL;
3054 s->loadsequence = 0;
3060 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3062 char basename[MAX_QPATH];
3064 Image_StripImageExtension(name, basename, sizeof(basename));
3066 if( last == NULL ) {
3068 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3069 item = r_skinframe.hash[hashindex];
3074 // linearly search through the hash bucket
3075 for( ; item ; item = item->next ) {
3076 if( !strcmp( item->basename, basename ) ) {
3083 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3087 char basename[MAX_QPATH];
3089 Image_StripImageExtension(name, basename, sizeof(basename));
3091 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3092 for (item = r_skinframe.hash[hashindex];item;item = item->next)
3093 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3097 rtexture_t *dyntexture;
3098 // check whether its a dynamic texture
3099 dyntexture = CL_GetDynTexture( basename );
3100 if (!add && !dyntexture)
3102 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3103 memset(item, 0, sizeof(*item));
3104 strlcpy(item->basename, basename, sizeof(item->basename));
3105 item->base = dyntexture; // either NULL or dyntexture handle
3106 item->textureflags = textureflags;
3107 item->comparewidth = comparewidth;
3108 item->compareheight = compareheight;
3109 item->comparecrc = comparecrc;
3110 item->next = r_skinframe.hash[hashindex];
3111 r_skinframe.hash[hashindex] = item;
3113 else if( item->base == NULL )
3115 rtexture_t *dyntexture;
3116 // check whether its a dynamic texture
3117 // 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]
3118 dyntexture = CL_GetDynTexture( basename );
3119 item->base = dyntexture; // either NULL or dyntexture handle
3122 R_SkinFrame_MarkUsed(item);
3126 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3128 unsigned long long avgcolor[5], wsum; \
3136 for(pix = 0; pix < cnt; ++pix) \
3139 for(comp = 0; comp < 3; ++comp) \
3141 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3144 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3146 for(comp = 0; comp < 3; ++comp) \
3147 avgcolor[comp] += getpixel * w; \
3150 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3151 avgcolor[4] += getpixel; \
3153 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3155 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3156 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3157 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3158 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3161 extern cvar_t gl_picmip;
3162 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3165 unsigned char *pixels;
3166 unsigned char *bumppixels;
3167 unsigned char *basepixels = NULL;
3168 int basepixels_width = 0;
3169 int basepixels_height = 0;
3170 skinframe_t *skinframe;
3171 rtexture_t *ddsbase = NULL;
3172 qboolean ddshasalpha = false;
3173 float ddsavgcolor[4];
3174 char basename[MAX_QPATH];
3175 int miplevel = R_PicmipForFlags(textureflags);
3176 int savemiplevel = miplevel;
3179 if (cls.state == ca_dedicated)
3182 // return an existing skinframe if already loaded
3183 // if loading of the first image fails, don't make a new skinframe as it
3184 // would cause all future lookups of this to be missing
3185 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3186 if (skinframe && skinframe->base)
3189 Image_StripImageExtension(name, basename, sizeof(basename));
3191 // check for DDS texture file first
3192 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3194 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3195 if (basepixels == NULL)
3199 // FIXME handle miplevel
3201 if (developer_loading.integer)
3202 Con_Printf("loading skin \"%s\"\n", name);
3204 // we've got some pixels to store, so really allocate this new texture now
3206 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3207 skinframe->stain = NULL;
3208 skinframe->merged = NULL;
3209 skinframe->base = NULL;
3210 skinframe->pants = NULL;
3211 skinframe->shirt = NULL;
3212 skinframe->nmap = NULL;
3213 skinframe->gloss = NULL;
3214 skinframe->glow = NULL;
3215 skinframe->fog = NULL;
3216 skinframe->reflect = NULL;
3217 skinframe->hasalpha = false;
3221 skinframe->base = ddsbase;
3222 skinframe->hasalpha = ddshasalpha;
3223 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3224 if (r_loadfog && skinframe->hasalpha)
3225 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3226 //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]);
3230 basepixels_width = image_width;
3231 basepixels_height = image_height;
3232 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);
3233 if (textureflags & TEXF_ALPHA)
3235 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3237 if (basepixels[j] < 255)
3239 skinframe->hasalpha = true;
3243 if (r_loadfog && skinframe->hasalpha)
3245 // has transparent pixels
3246 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3247 for (j = 0;j < image_width * image_height * 4;j += 4)
3252 pixels[j+3] = basepixels[j+3];
3254 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);
3258 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3259 //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]);
3260 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3261 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3262 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3263 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3268 mymiplevel = savemiplevel;
3269 if (r_loadnormalmap)
3270 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);
3271 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3273 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3274 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3275 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3276 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3279 // _norm is the name used by tenebrae and has been adopted as standard
3280 if (r_loadnormalmap && skinframe->nmap == NULL)
3282 mymiplevel = savemiplevel;
3283 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
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);
3289 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3291 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3292 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3293 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);
3295 Mem_Free(bumppixels);
3297 else if (r_shadow_bumpscale_basetexture.value > 0)
3299 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3300 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3301 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);
3304 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3305 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3308 // _luma is supported only for tenebrae compatibility
3309 // _glow is the preferred name
3310 mymiplevel = savemiplevel;
3311 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))))
3313 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);
3314 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3315 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3316 Mem_Free(pixels);pixels = NULL;
3319 mymiplevel = savemiplevel;
3320 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3322 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);
3323 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3324 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3329 mymiplevel = savemiplevel;
3330 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3332 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);
3333 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3334 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3339 mymiplevel = savemiplevel;
3340 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3342 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);
3343 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3344 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3349 mymiplevel = savemiplevel;
3350 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3352 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);
3353 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3354 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3360 Mem_Free(basepixels);
3365 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3366 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3369 unsigned char *temp1, *temp2;
3370 skinframe_t *skinframe;
3372 if (cls.state == ca_dedicated)
3375 // if already loaded just return it, otherwise make a new skinframe
3376 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3377 if (skinframe && skinframe->base)
3380 skinframe->stain = NULL;
3381 skinframe->merged = NULL;
3382 skinframe->base = NULL;
3383 skinframe->pants = NULL;
3384 skinframe->shirt = NULL;
3385 skinframe->nmap = NULL;
3386 skinframe->gloss = NULL;
3387 skinframe->glow = NULL;
3388 skinframe->fog = NULL;
3389 skinframe->reflect = NULL;
3390 skinframe->hasalpha = false;
3392 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3396 if (developer_loading.integer)
3397 Con_Printf("loading 32bit skin \"%s\"\n", name);
3399 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3401 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3402 temp2 = temp1 + width * height * 4;
3403 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3404 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);
3407 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3408 if (textureflags & TEXF_ALPHA)
3410 for (i = 3;i < width * height * 4;i += 4)
3412 if (skindata[i] < 255)
3414 skinframe->hasalpha = true;
3418 if (r_loadfog && skinframe->hasalpha)
3420 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3421 memcpy(fogpixels, skindata, width * height * 4);
3422 for (i = 0;i < width * height * 4;i += 4)
3423 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3424 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3425 Mem_Free(fogpixels);
3429 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3430 //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]);
3435 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3439 skinframe_t *skinframe;
3441 if (cls.state == ca_dedicated)
3444 // if already loaded just return it, otherwise make a new skinframe
3445 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3446 if (skinframe && skinframe->base)
3449 skinframe->stain = NULL;
3450 skinframe->merged = NULL;
3451 skinframe->base = NULL;
3452 skinframe->pants = NULL;
3453 skinframe->shirt = NULL;
3454 skinframe->nmap = NULL;
3455 skinframe->gloss = NULL;
3456 skinframe->glow = NULL;
3457 skinframe->fog = NULL;
3458 skinframe->reflect = NULL;
3459 skinframe->hasalpha = false;
3461 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3465 if (developer_loading.integer)
3466 Con_Printf("loading quake skin \"%s\"\n", name);
3468 // 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)
3469 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3470 memcpy(skinframe->qpixels, skindata, width*height);
3471 skinframe->qwidth = width;
3472 skinframe->qheight = height;
3475 for (i = 0;i < width * height;i++)
3476 featuresmask |= palette_featureflags[skindata[i]];
3478 skinframe->hasalpha = false;
3479 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3480 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3481 skinframe->qgeneratemerged = true;
3482 skinframe->qgeneratebase = skinframe->qhascolormapping;
3483 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3485 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3486 //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]);
3491 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3495 unsigned char *skindata;
3497 if (!skinframe->qpixels)
3500 if (!skinframe->qhascolormapping)
3501 colormapped = false;
3505 if (!skinframe->qgeneratebase)
3510 if (!skinframe->qgeneratemerged)
3514 width = skinframe->qwidth;
3515 height = skinframe->qheight;
3516 skindata = skinframe->qpixels;
3518 if (skinframe->qgeneratenmap)
3520 unsigned char *temp1, *temp2;
3521 skinframe->qgeneratenmap = false;
3522 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3523 temp2 = temp1 + width * height * 4;
3524 // use either a custom palette or the quake palette
3525 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3526 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3527 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);
3531 if (skinframe->qgenerateglow)
3533 skinframe->qgenerateglow = false;
3534 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
3539 skinframe->qgeneratebase = false;
3540 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);
3541 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);
3542 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);
3546 skinframe->qgeneratemerged = false;
3547 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);
3550 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3552 Mem_Free(skinframe->qpixels);
3553 skinframe->qpixels = NULL;
3557 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)
3560 skinframe_t *skinframe;
3562 if (cls.state == ca_dedicated)
3565 // if already loaded just return it, otherwise make a new skinframe
3566 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3567 if (skinframe && skinframe->base)
3570 skinframe->stain = NULL;
3571 skinframe->merged = NULL;
3572 skinframe->base = NULL;
3573 skinframe->pants = NULL;
3574 skinframe->shirt = NULL;
3575 skinframe->nmap = NULL;
3576 skinframe->gloss = NULL;
3577 skinframe->glow = NULL;
3578 skinframe->fog = NULL;
3579 skinframe->reflect = NULL;
3580 skinframe->hasalpha = false;
3582 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3586 if (developer_loading.integer)
3587 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3589 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3590 if (textureflags & TEXF_ALPHA)
3592 for (i = 0;i < width * height;i++)
3594 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3596 skinframe->hasalpha = true;
3600 if (r_loadfog && skinframe->hasalpha)
3601 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3604 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3605 //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]);
3610 skinframe_t *R_SkinFrame_LoadMissing(void)
3612 skinframe_t *skinframe;
3614 if (cls.state == ca_dedicated)
3617 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3618 skinframe->stain = NULL;
3619 skinframe->merged = NULL;
3620 skinframe->base = NULL;
3621 skinframe->pants = NULL;
3622 skinframe->shirt = NULL;
3623 skinframe->nmap = NULL;
3624 skinframe->gloss = NULL;
3625 skinframe->glow = NULL;
3626 skinframe->fog = NULL;
3627 skinframe->reflect = NULL;
3628 skinframe->hasalpha = false;
3630 skinframe->avgcolor[0] = rand() / RAND_MAX;
3631 skinframe->avgcolor[1] = rand() / RAND_MAX;
3632 skinframe->avgcolor[2] = rand() / RAND_MAX;
3633 skinframe->avgcolor[3] = 1;
3638 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3639 typedef struct suffixinfo_s
3642 qboolean flipx, flipy, flipdiagonal;
3645 static suffixinfo_t suffix[3][6] =
3648 {"px", false, false, false},
3649 {"nx", false, false, false},
3650 {"py", false, false, false},
3651 {"ny", false, false, false},
3652 {"pz", false, false, false},
3653 {"nz", false, false, false}
3656 {"posx", false, false, false},
3657 {"negx", false, false, false},
3658 {"posy", false, false, false},
3659 {"negy", false, false, false},
3660 {"posz", false, false, false},
3661 {"negz", false, false, false}
3664 {"rt", true, false, true},
3665 {"lf", false, true, true},
3666 {"ft", true, true, false},
3667 {"bk", false, false, false},
3668 {"up", true, false, true},
3669 {"dn", true, false, true}
3673 static int componentorder[4] = {0, 1, 2, 3};
3675 rtexture_t *R_LoadCubemap(const char *basename)
3677 int i, j, cubemapsize;
3678 unsigned char *cubemappixels, *image_buffer;
3679 rtexture_t *cubemaptexture;
3681 // must start 0 so the first loadimagepixels has no requested width/height
3683 cubemappixels = NULL;
3684 cubemaptexture = NULL;
3685 // keep trying different suffix groups (posx, px, rt) until one loads
3686 for (j = 0;j < 3 && !cubemappixels;j++)
3688 // load the 6 images in the suffix group
3689 for (i = 0;i < 6;i++)
3691 // generate an image name based on the base and and suffix
3692 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3694 if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3696 // an image loaded, make sure width and height are equal
3697 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3699 // if this is the first image to load successfully, allocate the cubemap memory
3700 if (!cubemappixels && image_width >= 1)
3702 cubemapsize = image_width;
3703 // note this clears to black, so unavailable sides are black
3704 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3706 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3708 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);
3711 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3713 Mem_Free(image_buffer);
3717 // if a cubemap loaded, upload it
3720 if (developer_loading.integer)
3721 Con_Printf("loading cubemap \"%s\"\n", basename);
3723 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);
3724 Mem_Free(cubemappixels);
3728 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3729 if (developer_loading.integer)
3731 Con_Printf("(tried tried images ");
3732 for (j = 0;j < 3;j++)
3733 for (i = 0;i < 6;i++)
3734 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3735 Con_Print(" and was unable to find any of them).\n");
3738 return cubemaptexture;
3741 rtexture_t *R_GetCubemap(const char *basename)
3744 for (i = 0;i < r_texture_numcubemaps;i++)
3745 if (r_texture_cubemaps[i] != NULL)
3746 if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3747 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3748 if (i >= MAX_CUBEMAPS || !r_main_mempool)
3749 return r_texture_whitecube;
3750 r_texture_numcubemaps++;
3751 r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3752 strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3753 r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3754 return r_texture_cubemaps[i]->texture;
3757 void R_FreeCubemap(const char *basename)
3761 for (i = 0;i < r_texture_numcubemaps;i++)
3763 if (r_texture_cubemaps[i] != NULL)
3765 if (r_texture_cubemaps[i]->texture)
3767 if (developer_loading.integer)
3768 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3769 R_FreeTexture(r_texture_cubemaps[i]->texture);
3770 Mem_Free(r_texture_cubemaps[i]);
3771 r_texture_cubemaps[i] = NULL;
3777 void R_FreeCubemaps(void)
3780 for (i = 0;i < r_texture_numcubemaps;i++)
3782 if (developer_loading.integer)
3783 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3784 if (r_texture_cubemaps[i] != NULL)
3786 if (r_texture_cubemaps[i]->texture)
3787 R_FreeTexture(r_texture_cubemaps[i]->texture);
3788 Mem_Free(r_texture_cubemaps[i]);
3791 r_texture_numcubemaps = 0;
3794 void R_Main_FreeViewCache(void)
3796 if (r_refdef.viewcache.entityvisible)
3797 Mem_Free(r_refdef.viewcache.entityvisible);
3798 if (r_refdef.viewcache.world_pvsbits)
3799 Mem_Free(r_refdef.viewcache.world_pvsbits);
3800 if (r_refdef.viewcache.world_leafvisible)
3801 Mem_Free(r_refdef.viewcache.world_leafvisible);
3802 if (r_refdef.viewcache.world_surfacevisible)
3803 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3804 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3807 void R_Main_ResizeViewCache(void)
3809 int numentities = r_refdef.scene.numentities;
3810 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3811 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3812 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3813 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3814 if (r_refdef.viewcache.maxentities < numentities)
3816 r_refdef.viewcache.maxentities = numentities;
3817 if (r_refdef.viewcache.entityvisible)
3818 Mem_Free(r_refdef.viewcache.entityvisible);
3819 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3821 if (r_refdef.viewcache.world_numclusters != numclusters)
3823 r_refdef.viewcache.world_numclusters = numclusters;
3824 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3825 if (r_refdef.viewcache.world_pvsbits)
3826 Mem_Free(r_refdef.viewcache.world_pvsbits);
3827 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3829 if (r_refdef.viewcache.world_numleafs != numleafs)
3831 r_refdef.viewcache.world_numleafs = numleafs;
3832 if (r_refdef.viewcache.world_leafvisible)
3833 Mem_Free(r_refdef.viewcache.world_leafvisible);
3834 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3836 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3838 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3839 if (r_refdef.viewcache.world_surfacevisible)
3840 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3841 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3845 extern rtexture_t *loadingscreentexture;
3846 void gl_main_start(void)
3848 loadingscreentexture = NULL;
3849 r_texture_blanknormalmap = NULL;
3850 r_texture_white = NULL;
3851 r_texture_grey128 = NULL;
3852 r_texture_black = NULL;
3853 r_texture_whitecube = NULL;
3854 r_texture_normalizationcube = NULL;
3855 r_texture_fogattenuation = NULL;
3856 r_texture_fogheighttexture = NULL;
3857 r_texture_gammaramps = NULL;
3858 r_texture_numcubemaps = 0;
3860 r_loaddds = r_texture_dds_load.integer != 0;
3861 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3863 switch(vid.renderpath)
3865 case RENDERPATH_GL20:
3866 case RENDERPATH_D3D9:
3867 case RENDERPATH_D3D10:
3868 case RENDERPATH_D3D11:
3869 case RENDERPATH_SOFT:
3870 case RENDERPATH_GLES2:
3871 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3872 Cvar_SetValueQuick(&gl_combine, 1);
3873 Cvar_SetValueQuick(&r_glsl, 1);
3874 r_loadnormalmap = true;
3878 case RENDERPATH_GL13:
3879 case RENDERPATH_GLES1:
3880 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3881 Cvar_SetValueQuick(&gl_combine, 1);
3882 Cvar_SetValueQuick(&r_glsl, 0);
3883 r_loadnormalmap = false;
3884 r_loadgloss = false;
3887 case RENDERPATH_GL11:
3888 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3889 Cvar_SetValueQuick(&gl_combine, 0);
3890 Cvar_SetValueQuick(&r_glsl, 0);
3891 r_loadnormalmap = false;
3892 r_loadgloss = false;
3898 R_FrameData_Reset();
3902 memset(r_queries, 0, sizeof(r_queries));
3904 r_qwskincache = NULL;
3905 r_qwskincache_size = 0;
3907 // due to caching of texture_t references, the collision cache must be reset
3908 Collision_Cache_Reset(true);
3910 // set up r_skinframe loading system for textures
3911 memset(&r_skinframe, 0, sizeof(r_skinframe));
3912 r_skinframe.loadsequence = 1;
3913 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3915 r_main_texturepool = R_AllocTexturePool();
3916 R_BuildBlankTextures();
3918 if (vid.support.arb_texture_cube_map)
3921 R_BuildNormalizationCube();
3923 r_texture_fogattenuation = NULL;
3924 r_texture_fogheighttexture = NULL;
3925 r_texture_gammaramps = NULL;
3926 //r_texture_fogintensity = NULL;
3927 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3928 memset(&r_waterstate, 0, sizeof(r_waterstate));
3929 r_glsl_permutation = NULL;
3930 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3931 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3932 glslshaderstring = NULL;
3934 r_hlsl_permutation = NULL;
3935 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3936 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
3938 hlslshaderstring = NULL;
3939 memset(&r_svbsp, 0, sizeof (r_svbsp));
3941 memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
3942 r_texture_numcubemaps = 0;
3944 r_refdef.fogmasktable_density = 0;
3947 void gl_main_shutdown(void)
3950 R_FrameData_Reset();
3952 R_Main_FreeViewCache();
3954 switch(vid.renderpath)
3956 case RENDERPATH_GL11:
3957 case RENDERPATH_GL13:
3958 case RENDERPATH_GL20:
3959 case RENDERPATH_GLES1:
3960 case RENDERPATH_GLES2:
3962 qglDeleteQueriesARB(r_maxqueries, r_queries);
3964 case RENDERPATH_D3D9:
3965 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3967 case RENDERPATH_D3D10:
3968 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3970 case RENDERPATH_D3D11:
3971 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3973 case RENDERPATH_SOFT:
3979 memset(r_queries, 0, sizeof(r_queries));
3981 r_qwskincache = NULL;
3982 r_qwskincache_size = 0;
3984 // clear out the r_skinframe state
3985 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3986 memset(&r_skinframe, 0, sizeof(r_skinframe));
3989 Mem_Free(r_svbsp.nodes);
3990 memset(&r_svbsp, 0, sizeof (r_svbsp));
3991 R_FreeTexturePool(&r_main_texturepool);
3992 loadingscreentexture = NULL;
3993 r_texture_blanknormalmap = NULL;
3994 r_texture_white = NULL;
3995 r_texture_grey128 = NULL;
3996 r_texture_black = NULL;
3997 r_texture_whitecube = NULL;
3998 r_texture_normalizationcube = NULL;
3999 r_texture_fogattenuation = NULL;
4000 r_texture_fogheighttexture = NULL;
4001 r_texture_gammaramps = NULL;
4002 r_texture_numcubemaps = 0;
4003 //r_texture_fogintensity = NULL;
4004 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4005 memset(&r_waterstate, 0, sizeof(r_waterstate));
4008 r_glsl_permutation = NULL;
4009 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4010 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4011 glslshaderstring = NULL;
4013 r_hlsl_permutation = NULL;
4014 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4015 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4017 hlslshaderstring = NULL;
4020 extern void CL_ParseEntityLump(char *entitystring);
4021 void gl_main_newmap(void)
4023 // FIXME: move this code to client
4024 char *entities, entname[MAX_QPATH];
4026 Mem_Free(r_qwskincache);
4027 r_qwskincache = NULL;
4028 r_qwskincache_size = 0;
4031 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4032 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4034 CL_ParseEntityLump(entities);
4038 if (cl.worldmodel->brush.entities)
4039 CL_ParseEntityLump(cl.worldmodel->brush.entities);
4041 R_Main_FreeViewCache();
4043 R_FrameData_Reset();
4046 void GL_Main_Init(void)
4048 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4050 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4051 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4052 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4053 if (gamemode == GAME_NEHAHRA)
4055 Cvar_RegisterVariable (&gl_fogenable);
4056 Cvar_RegisterVariable (&gl_fogdensity);
4057 Cvar_RegisterVariable (&gl_fogred);
4058 Cvar_RegisterVariable (&gl_foggreen);
4059 Cvar_RegisterVariable (&gl_fogblue);
4060 Cvar_RegisterVariable (&gl_fogstart);
4061 Cvar_RegisterVariable (&gl_fogend);
4062 Cvar_RegisterVariable (&gl_skyclip);
4064 Cvar_RegisterVariable(&r_motionblur);
4065 Cvar_RegisterVariable(&r_motionblur_maxblur);
4066 Cvar_RegisterVariable(&r_motionblur_bmin);
4067 Cvar_RegisterVariable(&r_motionblur_vmin);
4068 Cvar_RegisterVariable(&r_motionblur_vmax);
4069 Cvar_RegisterVariable(&r_motionblur_vcoeff);
4070 Cvar_RegisterVariable(&r_motionblur_randomize);
4071 Cvar_RegisterVariable(&r_damageblur);
4072 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4073 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4074 Cvar_RegisterVariable(&r_equalize_entities_by);
4075 Cvar_RegisterVariable(&r_equalize_entities_to);
4076 Cvar_RegisterVariable(&r_depthfirst);
4077 Cvar_RegisterVariable(&r_useinfinitefarclip);
4078 Cvar_RegisterVariable(&r_farclip_base);
4079 Cvar_RegisterVariable(&r_farclip_world);
4080 Cvar_RegisterVariable(&r_nearclip);
4081 Cvar_RegisterVariable(&r_deformvertexes);
4082 Cvar_RegisterVariable(&r_transparent);
4083 Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4084 Cvar_RegisterVariable(&r_showoverdraw);
4085 Cvar_RegisterVariable(&r_showbboxes);
4086 Cvar_RegisterVariable(&r_showsurfaces);
4087 Cvar_RegisterVariable(&r_showtris);
4088 Cvar_RegisterVariable(&r_shownormals);
4089 Cvar_RegisterVariable(&r_showlighting);
4090 Cvar_RegisterVariable(&r_showshadowvolumes);
4091 Cvar_RegisterVariable(&r_showcollisionbrushes);
4092 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4093 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4094 Cvar_RegisterVariable(&r_showdisabledepthtest);
4095 Cvar_RegisterVariable(&r_drawportals);
4096 Cvar_RegisterVariable(&r_drawentities);
4097 Cvar_RegisterVariable(&r_draw2d);
4098 Cvar_RegisterVariable(&r_drawworld);
4099 Cvar_RegisterVariable(&r_cullentities_trace);
4100 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4101 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4102 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4103 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4104 Cvar_RegisterVariable(&r_drawviewmodel);
4105 Cvar_RegisterVariable(&r_drawexteriormodel);
4106 Cvar_RegisterVariable(&r_speeds);
4107 Cvar_RegisterVariable(&r_fullbrights);
4108 Cvar_RegisterVariable(&r_wateralpha);
4109 Cvar_RegisterVariable(&r_dynamic);
4110 Cvar_RegisterVariable(&r_fakelight);
4111 Cvar_RegisterVariable(&r_fakelight_intensity);
4112 Cvar_RegisterVariable(&r_fullbright);
4113 Cvar_RegisterVariable(&r_shadows);
4114 Cvar_RegisterVariable(&r_shadows_darken);
4115 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4116 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4117 Cvar_RegisterVariable(&r_shadows_throwdistance);
4118 Cvar_RegisterVariable(&r_shadows_throwdirection);
4119 Cvar_RegisterVariable(&r_shadows_focus);
4120 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4121 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4122 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4123 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4124 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4125 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4126 Cvar_RegisterVariable(&r_fog_exp2);
4127 Cvar_RegisterVariable(&r_fog_clear);
4128 Cvar_RegisterVariable(&r_drawfog);
4129 Cvar_RegisterVariable(&r_transparentdepthmasking);
4130 Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4131 Cvar_RegisterVariable(&r_transparent_sortarraysize);
4132 Cvar_RegisterVariable(&r_texture_dds_load);
4133 Cvar_RegisterVariable(&r_texture_dds_save);
4134 Cvar_RegisterVariable(&r_textureunits);
4135 Cvar_RegisterVariable(&gl_combine);
4136 Cvar_RegisterVariable(&r_viewfbo);
4137 Cvar_RegisterVariable(&r_viewscale);
4138 Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4139 Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4140 Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4141 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4142 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4143 Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4144 Cvar_RegisterVariable(&r_glsl);
4145 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4146 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4147 Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4148 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4149 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4150 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4151 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4152 Cvar_RegisterVariable(&r_glsl_postprocess);
4153 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4154 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4155 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4156 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4157 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4158 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4159 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4160 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4162 Cvar_RegisterVariable(&r_water);
4163 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4164 Cvar_RegisterVariable(&r_water_clippingplanebias);
4165 Cvar_RegisterVariable(&r_water_refractdistort);
4166 Cvar_RegisterVariable(&r_water_reflectdistort);
4167 Cvar_RegisterVariable(&r_water_scissormode);
4168 Cvar_RegisterVariable(&r_water_lowquality);
4170 Cvar_RegisterVariable(&r_lerpsprites);
4171 Cvar_RegisterVariable(&r_lerpmodels);
4172 Cvar_RegisterVariable(&r_lerplightstyles);
4173 Cvar_RegisterVariable(&r_waterscroll);
4174 Cvar_RegisterVariable(&r_bloom);
4175 Cvar_RegisterVariable(&r_bloom_colorscale);
4176 Cvar_RegisterVariable(&r_bloom_brighten);
4177 Cvar_RegisterVariable(&r_bloom_blur);
4178 Cvar_RegisterVariable(&r_bloom_resolution);
4179 Cvar_RegisterVariable(&r_bloom_colorexponent);
4180 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4181 Cvar_RegisterVariable(&r_hdr);
4182 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4183 Cvar_RegisterVariable(&r_hdr_glowintensity);
4184 Cvar_RegisterVariable(&r_hdr_range);
4185 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4186 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4187 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4188 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4189 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4190 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4191 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4192 Cvar_RegisterVariable(&developer_texturelogging);
4193 Cvar_RegisterVariable(&gl_lightmaps);
4194 Cvar_RegisterVariable(&r_test);
4195 Cvar_RegisterVariable(&r_glsl_saturation);
4196 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4197 Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4198 Cvar_RegisterVariable(&r_framedatasize);
4199 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4200 Cvar_SetValue("r_fullbrights", 0);
4201 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4203 Cvar_RegisterVariable(&r_track_sprites);
4204 Cvar_RegisterVariable(&r_track_sprites_flags);
4205 Cvar_RegisterVariable(&r_track_sprites_scalew);
4206 Cvar_RegisterVariable(&r_track_sprites_scaleh);
4207 Cvar_RegisterVariable(&r_overheadsprites_perspective);
4208 Cvar_RegisterVariable(&r_overheadsprites_pushback);
4209 Cvar_RegisterVariable(&r_overheadsprites_scalex);
4210 Cvar_RegisterVariable(&r_overheadsprites_scaley);
4213 extern void R_Textures_Init(void);
4214 extern void GL_Draw_Init(void);
4215 extern void GL_Main_Init(void);
4216 extern void R_Shadow_Init(void);
4217 extern void R_Sky_Init(void);
4218 extern void GL_Surf_Init(void);
4219 extern void R_Particles_Init(void);
4220 extern void R_Explosion_Init(void);
4221 extern void gl_backend_init(void);
4222 extern void Sbar_Init(void);
4223 extern void R_LightningBeams_Init(void);
4224 extern void Mod_RenderInit(void);
4225 extern void Font_Init(void);
4227 void Render_Init(void)
4240 R_LightningBeams_Init();
4249 extern char *ENGINE_EXTENSIONS;
4252 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4253 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4254 gl_version = (const char *)qglGetString(GL_VERSION);
4255 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4259 if (!gl_platformextensions)
4260 gl_platformextensions = "";
4262 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4263 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4264 Con_Printf("GL_VERSION: %s\n", gl_version);
4265 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4266 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4268 VID_CheckExtensions();
4270 // LordHavoc: report supported extensions
4271 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4273 // clear to black (loading plaque will be seen over this)
4274 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4277 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4281 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4283 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4286 p = r_refdef.view.frustum + i;
4291 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4295 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4299 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4303 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4307 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4311 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4315 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4319 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4327 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4331 for (i = 0;i < numplanes;i++)
4338 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4342 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4346 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4350 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4354 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4358 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4362 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4366 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4374 //==================================================================================
4376 // LordHavoc: this stores temporary data used within the same frame
4378 typedef struct r_framedata_mem_s
4380 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4381 size_t size; // how much usable space
4382 size_t current; // how much space in use
4383 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4384 size_t wantedsize; // how much space was allocated
4385 unsigned char *data; // start of real data (16byte aligned)
4389 static r_framedata_mem_t *r_framedata_mem;
4391 void R_FrameData_Reset(void)
4393 while (r_framedata_mem)
4395 r_framedata_mem_t *next = r_framedata_mem->purge;
4396 Mem_Free(r_framedata_mem);
4397 r_framedata_mem = next;
4401 void R_FrameData_Resize(void)
4404 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4405 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4406 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4408 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4409 newmem->wantedsize = wantedsize;
4410 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4411 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4412 newmem->current = 0;
4414 newmem->purge = r_framedata_mem;
4415 r_framedata_mem = newmem;
4419 void R_FrameData_NewFrame(void)
4421 R_FrameData_Resize();
4422 if (!r_framedata_mem)
4424 // if we ran out of space on the last frame, free the old memory now
4425 while (r_framedata_mem->purge)
4427 // repeatedly remove the second item in the list, leaving only head
4428 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4429 Mem_Free(r_framedata_mem->purge);
4430 r_framedata_mem->purge = next;
4432 // reset the current mem pointer
4433 r_framedata_mem->current = 0;
4434 r_framedata_mem->mark = 0;
4437 void *R_FrameData_Alloc(size_t size)
4441 // align to 16 byte boundary - the data pointer is already aligned, so we
4442 // only need to ensure the size of every allocation is also aligned
4443 size = (size + 15) & ~15;
4445 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4447 // emergency - we ran out of space, allocate more memory
4448 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4449 R_FrameData_Resize();
4452 data = r_framedata_mem->data + r_framedata_mem->current;
4453 r_framedata_mem->current += size;
4455 // count the usage for stats
4456 r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4457 r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4459 return (void *)data;
4462 void *R_FrameData_Store(size_t size, void *data)
4464 void *d = R_FrameData_Alloc(size);
4466 memcpy(d, data, size);
4470 void R_FrameData_SetMark(void)
4472 if (!r_framedata_mem)
4474 r_framedata_mem->mark = r_framedata_mem->current;
4477 void R_FrameData_ReturnToMark(void)
4479 if (!r_framedata_mem)
4481 r_framedata_mem->current = r_framedata_mem->mark;
4484 //==================================================================================
4486 // LordHavoc: animcache originally written by Echon, rewritten since then
4489 * Animation cache prevents re-generating mesh data for an animated model
4490 * multiple times in one frame for lighting, shadowing, reflections, etc.
4493 void R_AnimCache_Free(void)
4497 void R_AnimCache_ClearCache(void)
4500 entity_render_t *ent;
4502 for (i = 0;i < r_refdef.scene.numentities;i++)
4504 ent = r_refdef.scene.entities[i];
4505 ent->animcache_vertex3f = NULL;
4506 ent->animcache_normal3f = NULL;
4507 ent->animcache_svector3f = NULL;
4508 ent->animcache_tvector3f = NULL;
4509 ent->animcache_vertexmesh = NULL;
4510 ent->animcache_vertex3fbuffer = NULL;
4511 ent->animcache_vertexmeshbuffer = NULL;
4515 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4519 // check if we need the meshbuffers
4520 if (!vid.useinterleavedarrays)
4523 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4524 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4525 // TODO: upload vertex3f buffer?
4526 if (ent->animcache_vertexmesh)
4528 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4529 for (i = 0;i < numvertices;i++)
4530 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4531 if (ent->animcache_svector3f)
4532 for (i = 0;i < numvertices;i++)
4533 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4534 if (ent->animcache_tvector3f)
4535 for (i = 0;i < numvertices;i++)
4536 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4537 if (ent->animcache_normal3f)
4538 for (i = 0;i < numvertices;i++)
4539 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4540 // TODO: upload vertexmeshbuffer?
4544 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4546 dp_model_t *model = ent->model;
4548 // see if it's already cached this frame
4549 if (ent->animcache_vertex3f)
4551 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4552 if (wantnormals || wanttangents)
4554 if (ent->animcache_normal3f)
4555 wantnormals = false;
4556 if (ent->animcache_svector3f)
4557 wanttangents = false;
4558 if (wantnormals || wanttangents)
4560 numvertices = model->surfmesh.num_vertices;
4562 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4565 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4566 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4568 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4569 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4575 // see if this ent is worth caching
4576 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4578 // get some memory for this entity and generate mesh data
4579 numvertices = model->surfmesh.num_vertices;
4580 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4582 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4585 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4586 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4588 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4589 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4594 void R_AnimCache_CacheVisibleEntities(void)
4597 qboolean wantnormals = true;
4598 qboolean wanttangents = !r_showsurfaces.integer;
4600 switch(vid.renderpath)
4602 case RENDERPATH_GL20:
4603 case RENDERPATH_D3D9:
4604 case RENDERPATH_D3D10:
4605 case RENDERPATH_D3D11:
4606 case RENDERPATH_GLES2:
4608 case RENDERPATH_GL11:
4609 case RENDERPATH_GL13:
4610 case RENDERPATH_GLES1:
4611 wanttangents = false;
4613 case RENDERPATH_SOFT:
4617 if (r_shownormals.integer)
4618 wanttangents = wantnormals = true;
4620 // TODO: thread this
4621 // NOTE: R_PrepareRTLights() also caches entities
4623 for (i = 0;i < r_refdef.scene.numentities;i++)
4624 if (r_refdef.viewcache.entityvisible[i])
4625 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4628 //==================================================================================
4630 static void R_View_UpdateEntityLighting (void)
4633 entity_render_t *ent;
4634 vec3_t tempdiffusenormal, avg;
4635 vec_t f, fa, fd, fdd;
4636 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4638 for (i = 0;i < r_refdef.scene.numentities;i++)
4640 ent = r_refdef.scene.entities[i];
4642 // skip unseen models
4643 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4647 if (ent->model && ent->model->brush.num_leafs)
4649 // TODO: use modellight for r_ambient settings on world?
4650 VectorSet(ent->modellight_ambient, 0, 0, 0);
4651 VectorSet(ent->modellight_diffuse, 0, 0, 0);
4652 VectorSet(ent->modellight_lightdir, 0, 0, 1);
4656 // fetch the lighting from the worldmodel data
4657 VectorClear(ent->modellight_ambient);
4658 VectorClear(ent->modellight_diffuse);
4659 VectorClear(tempdiffusenormal);
4660 if (ent->flags & RENDER_LIGHT)
4663 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4665 // complete lightning for lit sprites
4666 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4667 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4669 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4670 org[2] = org[2] + r_overheadsprites_pushback.value;
4671 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4674 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4676 if(ent->flags & RENDER_EQUALIZE)
4678 // first fix up ambient lighting...
4679 if(r_equalize_entities_minambient.value > 0)
4681 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4684 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4685 if(fa < r_equalize_entities_minambient.value * fd)
4688 // fa'/fd' = minambient
4689 // fa'+0.25*fd' = fa+0.25*fd
4691 // fa' = fd' * minambient
4692 // fd'*(0.25+minambient) = fa+0.25*fd
4694 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4695 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4697 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4698 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
4699 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4700 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4705 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4707 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4708 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4712 // adjust brightness and saturation to target
4713 avg[0] = avg[1] = avg[2] = fa / f;
4714 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4715 avg[0] = avg[1] = avg[2] = fd / f;
4716 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4722 VectorSet(ent->modellight_ambient, 1, 1, 1);
4724 // move the light direction into modelspace coordinates for lighting code
4725 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4726 if(VectorLength2(ent->modellight_lightdir) == 0)
4727 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4728 VectorNormalize(ent->modellight_lightdir);
4732 #define MAX_LINEOFSIGHTTRACES 64
4734 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4737 vec3_t boxmins, boxmaxs;
4740 dp_model_t *model = r_refdef.scene.worldmodel;
4742 if (!model || !model->brush.TraceLineOfSight)
4745 // expand the box a little
4746 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4747 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4748 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4749 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4750 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4751 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4753 // return true if eye is inside enlarged box
4754 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4758 VectorCopy(eye, start);
4759 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4760 if (model->brush.TraceLineOfSight(model, start, end))
4763 // try various random positions
4764 for (i = 0;i < numsamples;i++)
4766 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4767 if (model->brush.TraceLineOfSight(model, start, end))
4775 static void R_View_UpdateEntityVisible (void)
4780 entity_render_t *ent;
4782 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4783 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4784 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
4785 : RENDER_EXTERIORMODEL;
4786 if (!r_drawviewmodel.integer)
4787 renderimask |= RENDER_VIEWMODEL;
4788 if (!r_drawexteriormodel.integer)
4789 renderimask |= RENDER_EXTERIORMODEL;
4790 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4792 // worldmodel can check visibility
4793 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4794 for (i = 0;i < r_refdef.scene.numentities;i++)
4796 ent = r_refdef.scene.entities[i];
4797 if (!(ent->flags & renderimask))
4798 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)))
4799 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))
4800 r_refdef.viewcache.entityvisible[i] = true;
4805 // no worldmodel or it can't check visibility
4806 for (i = 0;i < r_refdef.scene.numentities;i++)
4808 ent = r_refdef.scene.entities[i];
4809 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));
4812 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
4813 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4815 for (i = 0;i < r_refdef.scene.numentities;i++)
4817 if (!r_refdef.viewcache.entityvisible[i])
4819 ent = r_refdef.scene.entities[i];
4820 if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4822 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4824 continue; // temp entities do pvs only
4825 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4826 ent->last_trace_visibility = realtime;
4827 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4828 r_refdef.viewcache.entityvisible[i] = 0;
4834 /// only used if skyrendermasked, and normally returns false
4835 int R_DrawBrushModelsSky (void)
4838 entity_render_t *ent;
4841 for (i = 0;i < r_refdef.scene.numentities;i++)
4843 if (!r_refdef.viewcache.entityvisible[i])
4845 ent = r_refdef.scene.entities[i];
4846 if (!ent->model || !ent->model->DrawSky)
4848 ent->model->DrawSky(ent);
4854 static void R_DrawNoModel(entity_render_t *ent);
4855 static void R_DrawModels(void)
4858 entity_render_t *ent;
4860 for (i = 0;i < r_refdef.scene.numentities;i++)
4862 if (!r_refdef.viewcache.entityvisible[i])
4864 ent = r_refdef.scene.entities[i];
4865 r_refdef.stats.entities++;
4867 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
4870 Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
4871 Con_Printf("R_DrawModels\n");
4872 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]);
4873 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);
4874 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);
4877 if (ent->model && ent->model->Draw != NULL)
4878 ent->model->Draw(ent);
4884 static void R_DrawModelsDepth(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->DrawDepth != NULL)
4895 ent->model->DrawDepth(ent);
4899 static void R_DrawModelsDebug(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->DrawDebug != NULL)
4910 ent->model->DrawDebug(ent);
4914 static void R_DrawModelsAddWaterPlanes(void)
4917 entity_render_t *ent;
4919 for (i = 0;i < r_refdef.scene.numentities;i++)
4921 if (!r_refdef.viewcache.entityvisible[i])
4923 ent = r_refdef.scene.entities[i];
4924 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4925 ent->model->DrawAddWaterPlanes(ent);
4929 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4931 if (r_hdr_irisadaptation.integer)
4935 vec3_t diffusenormal;
4940 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4941 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
4942 brightness = max(0.0000001f, brightness);
4943 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4944 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4945 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
4946 current = r_hdr_irisadaptation_value.value;
4948 current = min(current + adjust, goal);
4949 else if (current > goal)
4950 current = max(current - adjust, goal);
4951 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4952 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4954 else if (r_hdr_irisadaptation_value.value != 1.0f)
4955 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4958 static void R_View_SetFrustum(const int *scissor)
4961 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
4962 vec3_t forward, left, up, origin, v;
4966 // flipped x coordinates (because x points left here)
4967 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4968 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4970 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
4971 switch(vid.renderpath)
4973 case RENDERPATH_D3D9:
4974 case RENDERPATH_D3D10:
4975 case RENDERPATH_D3D11:
4976 // non-flipped y coordinates
4977 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4978 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4980 case RENDERPATH_SOFT:
4981 case RENDERPATH_GL11:
4982 case RENDERPATH_GL13:
4983 case RENDERPATH_GL20:
4984 case RENDERPATH_GLES1:
4985 case RENDERPATH_GLES2:
4986 // non-flipped y coordinates
4987 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4988 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4993 // we can't trust r_refdef.view.forward and friends in reflected scenes
4994 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4997 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4998 r_refdef.view.frustum[0].normal[1] = 0 - 0;
4999 r_refdef.view.frustum[0].normal[2] = -1 - 0;
5000 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5001 r_refdef.view.frustum[1].normal[1] = 0 + 0;
5002 r_refdef.view.frustum[1].normal[2] = -1 + 0;
5003 r_refdef.view.frustum[2].normal[0] = 0 - 0;
5004 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5005 r_refdef.view.frustum[2].normal[2] = -1 - 0;
5006 r_refdef.view.frustum[3].normal[0] = 0 + 0;
5007 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5008 r_refdef.view.frustum[3].normal[2] = -1 + 0;
5012 zNear = r_refdef.nearclip;
5013 nudge = 1.0 - 1.0 / (1<<23);
5014 r_refdef.view.frustum[4].normal[0] = 0 - 0;
5015 r_refdef.view.frustum[4].normal[1] = 0 - 0;
5016 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5017 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5018 r_refdef.view.frustum[5].normal[0] = 0 + 0;
5019 r_refdef.view.frustum[5].normal[1] = 0 + 0;
5020 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5021 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5027 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5028 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5029 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5030 r_refdef.view.frustum[0].dist = m[15] - m[12];
5032 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5033 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5034 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5035 r_refdef.view.frustum[1].dist = m[15] + m[12];
5037 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5038 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5039 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5040 r_refdef.view.frustum[2].dist = m[15] - m[13];
5042 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5043 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5044 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5045 r_refdef.view.frustum[3].dist = m[15] + m[13];
5047 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5048 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5049 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5050 r_refdef.view.frustum[4].dist = m[15] - m[14];
5052 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5053 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5054 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5055 r_refdef.view.frustum[5].dist = m[15] + m[14];
5058 if (r_refdef.view.useperspective)
5060 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5061 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]);
5062 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]);
5063 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]);
5064 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]);
5066 // then the normals from the corners relative to origin
5067 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5068 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5069 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5070 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5072 // in a NORMAL view, forward cross left == up
5073 // in a REFLECTED view, forward cross left == down
5074 // so our cross products above need to be adjusted for a left handed coordinate system
5075 CrossProduct(forward, left, v);
5076 if(DotProduct(v, up) < 0)
5078 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5079 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5080 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5081 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5084 // Leaving those out was a mistake, those were in the old code, and they
5085 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5086 // I couldn't reproduce it after adding those normalizations. --blub
5087 VectorNormalize(r_refdef.view.frustum[0].normal);
5088 VectorNormalize(r_refdef.view.frustum[1].normal);
5089 VectorNormalize(r_refdef.view.frustum[2].normal);
5090 VectorNormalize(r_refdef.view.frustum[3].normal);
5092 // make the corners absolute
5093 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5094 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5095 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5096 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5099 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5101 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5102 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5103 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5104 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5105 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5109 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5110 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5111 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5112 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5113 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5114 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5115 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5116 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5117 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5118 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5120 r_refdef.view.numfrustumplanes = 5;
5122 if (r_refdef.view.useclipplane)
5124 r_refdef.view.numfrustumplanes = 6;
5125 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5128 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5129 PlaneClassify(r_refdef.view.frustum + i);
5131 // LordHavoc: note to all quake engine coders, Quake had a special case
5132 // for 90 degrees which assumed a square view (wrong), so I removed it,
5133 // Quake2 has it disabled as well.
5135 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5136 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5137 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5138 //PlaneClassify(&frustum[0]);
5140 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5141 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5142 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5143 //PlaneClassify(&frustum[1]);
5145 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5146 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5147 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5148 //PlaneClassify(&frustum[2]);
5150 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5151 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5152 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5153 //PlaneClassify(&frustum[3]);
5156 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5157 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5158 //PlaneClassify(&frustum[4]);
5161 void R_View_UpdateWithScissor(const int *myscissor)
5163 R_Main_ResizeViewCache();
5164 R_View_SetFrustum(myscissor);
5165 R_View_WorldVisibility(r_refdef.view.useclipplane);
5166 R_View_UpdateEntityVisible();
5167 R_View_UpdateEntityLighting();
5170 void R_View_Update(void)
5172 R_Main_ResizeViewCache();
5173 R_View_SetFrustum(NULL);
5174 R_View_WorldVisibility(r_refdef.view.useclipplane);
5175 R_View_UpdateEntityVisible();
5176 R_View_UpdateEntityLighting();
5179 float viewscalefpsadjusted = 1.0f;
5181 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5183 float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5184 scale = bound(0.03125f, scale, 1.0f);
5185 *outwidth = (int)ceil(width * scale);
5186 *outheight = (int)ceil(height * scale);
5189 void R_Mesh_SetMainRenderTargets(void)
5191 if (r_bloomstate.fbo_framebuffer)
5192 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5194 R_Mesh_ResetRenderTargets();
5197 void R_SetupView(qboolean allowwaterclippingplane)
5199 const float *customclipplane = NULL;
5201 int scaledwidth, scaledheight;
5202 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5204 // LordHavoc: couldn't figure out how to make this approach the
5205 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5206 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5207 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5208 dist = r_refdef.view.clipplane.dist;
5209 plane[0] = r_refdef.view.clipplane.normal[0];
5210 plane[1] = r_refdef.view.clipplane.normal[1];
5211 plane[2] = r_refdef.view.clipplane.normal[2];
5213 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5216 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5217 if (!r_refdef.view.useperspective)
5218 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);
5219 else if (vid.stencil && r_useinfinitefarclip.integer)
5220 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);
5222 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);
5223 R_Mesh_SetMainRenderTargets();
5224 R_SetViewport(&r_refdef.view.viewport);
5225 if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5227 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5228 float screenplane[4];
5229 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5230 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5231 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5232 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5233 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5237 void R_EntityMatrix(const matrix4x4_t *matrix)
5239 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5241 gl_modelmatrixchanged = false;
5242 gl_modelmatrix = *matrix;
5243 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5244 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5245 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5246 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5248 switch(vid.renderpath)
5250 case RENDERPATH_D3D9:
5252 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5253 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5256 case RENDERPATH_D3D10:
5257 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5259 case RENDERPATH_D3D11:
5260 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5262 case RENDERPATH_GL11:
5263 case RENDERPATH_GL13:
5264 case RENDERPATH_GLES1:
5265 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5267 case RENDERPATH_SOFT:
5268 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5269 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5271 case RENDERPATH_GL20:
5272 case RENDERPATH_GLES2:
5273 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5274 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5280 void R_ResetViewRendering2D(void)
5282 r_viewport_t viewport;
5285 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5286 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);
5287 R_Mesh_ResetRenderTargets();
5288 R_SetViewport(&viewport);
5289 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5290 GL_Color(1, 1, 1, 1);
5291 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5292 GL_BlendFunc(GL_ONE, GL_ZERO);
5293 GL_ScissorTest(false);
5294 GL_DepthMask(false);
5295 GL_DepthRange(0, 1);
5296 GL_DepthTest(false);
5297 GL_DepthFunc(GL_LEQUAL);
5298 R_EntityMatrix(&identitymatrix);
5299 R_Mesh_ResetTextureState();
5300 GL_PolygonOffset(0, 0);
5301 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5302 switch(vid.renderpath)
5304 case RENDERPATH_GL11:
5305 case RENDERPATH_GL13:
5306 case RENDERPATH_GL20:
5307 case RENDERPATH_GLES1:
5308 case RENDERPATH_GLES2:
5309 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5311 case RENDERPATH_D3D9:
5312 case RENDERPATH_D3D10:
5313 case RENDERPATH_D3D11:
5314 case RENDERPATH_SOFT:
5317 GL_CullFace(GL_NONE);
5320 void R_ResetViewRendering3D(void)
5325 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5326 GL_Color(1, 1, 1, 1);
5327 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5328 GL_BlendFunc(GL_ONE, GL_ZERO);
5329 GL_ScissorTest(true);
5331 GL_DepthRange(0, 1);
5333 GL_DepthFunc(GL_LEQUAL);
5334 R_EntityMatrix(&identitymatrix);
5335 R_Mesh_ResetTextureState();
5336 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5337 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5338 switch(vid.renderpath)
5340 case RENDERPATH_GL11:
5341 case RENDERPATH_GL13:
5342 case RENDERPATH_GL20:
5343 case RENDERPATH_GLES1:
5344 case RENDERPATH_GLES2:
5345 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5347 case RENDERPATH_D3D9:
5348 case RENDERPATH_D3D10:
5349 case RENDERPATH_D3D11:
5350 case RENDERPATH_SOFT:
5353 GL_CullFace(r_refdef.view.cullface_back);
5358 R_RenderView_UpdateViewVectors
5361 static void R_RenderView_UpdateViewVectors(void)
5363 // break apart the view matrix into vectors for various purposes
5364 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5365 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5366 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5367 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5368 // make an inverted copy of the view matrix for tracking sprites
5369 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5372 void R_RenderScene(void);
5373 void R_RenderWaterPlanes(void);
5375 static void R_Water_StartFrame(void)
5378 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5379 r_waterstate_waterplane_t *p;
5381 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5384 switch(vid.renderpath)
5386 case RENDERPATH_GL20:
5387 case RENDERPATH_D3D9:
5388 case RENDERPATH_D3D10:
5389 case RENDERPATH_D3D11:
5390 case RENDERPATH_SOFT:
5391 case RENDERPATH_GLES2:
5393 case RENDERPATH_GL11:
5394 case RENDERPATH_GL13:
5395 case RENDERPATH_GLES1:
5399 // set waterwidth and waterheight to the water resolution that will be
5400 // used (often less than the screen resolution for faster rendering)
5401 R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5403 // calculate desired texture sizes
5404 // can't use water if the card does not support the texture size
5405 if (!r_water.integer || r_showsurfaces.integer)
5406 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5407 else if (vid.support.arb_texture_non_power_of_two)
5409 texturewidth = waterwidth;
5410 textureheight = waterheight;
5411 camerawidth = waterwidth;
5412 cameraheight = waterheight;
5416 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5417 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5418 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
5419 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
5422 // allocate textures as needed
5423 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5425 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5426 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5428 if (p->texture_refraction)
5429 R_FreeTexture(p->texture_refraction);
5430 p->texture_refraction = NULL;
5431 if (p->texture_reflection)
5432 R_FreeTexture(p->texture_reflection);
5433 p->texture_reflection = NULL;
5434 if (p->texture_camera)
5435 R_FreeTexture(p->texture_camera);
5436 p->texture_camera = NULL;
5438 memset(&r_waterstate, 0, sizeof(r_waterstate));
5439 r_waterstate.texturewidth = texturewidth;
5440 r_waterstate.textureheight = textureheight;
5441 r_waterstate.camerawidth = camerawidth;
5442 r_waterstate.cameraheight = cameraheight;
5445 if (r_waterstate.texturewidth)
5447 int scaledwidth, scaledheight;
5449 r_waterstate.enabled = true;
5451 // when doing a reduced render (HDR) we want to use a smaller area
5452 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5453 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5454 R_GetScaledViewSize(r_waterstate.waterwidth, r_waterstate.waterheight, &scaledwidth, &scaledheight);
5456 // set up variables that will be used in shader setup
5457 r_waterstate.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5458 r_waterstate.screenscale[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5459 r_waterstate.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5460 r_waterstate.screencenter[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5463 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5464 r_waterstate.numwaterplanes = 0;
5467 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5469 int triangleindex, planeindex;
5475 r_waterstate_waterplane_t *p;
5476 texture_t *t = R_GetCurrentTexture(surface->texture);
5478 // just use the first triangle with a valid normal for any decisions
5479 VectorClear(normal);
5480 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5482 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5483 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5484 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5485 TriangleNormal(vert[0], vert[1], vert[2], normal);
5486 if (VectorLength2(normal) >= 0.001)
5490 VectorCopy(normal, plane.normal);
5491 VectorNormalize(plane.normal);
5492 plane.dist = DotProduct(vert[0], plane.normal);
5493 PlaneClassify(&plane);
5494 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5496 // skip backfaces (except if nocullface is set)
5497 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5499 VectorNegate(plane.normal, plane.normal);
5501 PlaneClassify(&plane);
5505 // find a matching plane if there is one
5506 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5507 if(p->camera_entity == t->camera_entity)
5508 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5510 if (planeindex >= r_waterstate.maxwaterplanes)
5511 return; // nothing we can do, out of planes
5513 // if this triangle does not fit any known plane rendered this frame, add one
5514 if (planeindex >= r_waterstate.numwaterplanes)
5516 // store the new plane
5517 r_waterstate.numwaterplanes++;
5519 // clear materialflags and pvs
5520 p->materialflags = 0;
5521 p->pvsvalid = false;
5522 p->camera_entity = t->camera_entity;
5523 VectorCopy(surface->mins, p->mins);
5524 VectorCopy(surface->maxs, p->maxs);
5529 p->mins[0] = min(p->mins[0], surface->mins[0]);
5530 p->mins[1] = min(p->mins[1], surface->mins[1]);
5531 p->mins[2] = min(p->mins[2], surface->mins[2]);
5532 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5533 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5534 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5536 // merge this surface's materialflags into the waterplane
5537 p->materialflags |= t->currentmaterialflags;
5538 if(!(p->materialflags & MATERIALFLAG_CAMERA))
5540 // merge this surface's PVS into the waterplane
5541 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5542 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5543 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5545 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5551 extern cvar_t r_drawparticles;
5552 extern cvar_t r_drawdecals;
5554 static void R_Water_ProcessPlanes(void)
5557 r_refdef_view_t originalview;
5558 r_refdef_view_t myview;
5559 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;
5560 r_waterstate_waterplane_t *p;
5563 originalview = r_refdef.view;
5565 // lowquality hack, temporarily shut down some cvars and restore afterwards
5566 qualityreduction = r_water_lowquality.integer;
5567 if (qualityreduction > 0)
5569 if (qualityreduction >= 1)
5571 old_r_shadows = r_shadows.integer;
5572 old_r_worldrtlight = r_shadow_realtime_world.integer;
5573 old_r_dlight = r_shadow_realtime_dlight.integer;
5574 Cvar_SetValueQuick(&r_shadows, 0);
5575 Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5576 Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5578 if (qualityreduction >= 2)
5580 old_r_dynamic = r_dynamic.integer;
5581 old_r_particles = r_drawparticles.integer;
5582 old_r_decals = r_drawdecals.integer;
5583 Cvar_SetValueQuick(&r_dynamic, 0);
5584 Cvar_SetValueQuick(&r_drawparticles, 0);
5585 Cvar_SetValueQuick(&r_drawdecals, 0);
5589 // make sure enough textures are allocated
5590 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5592 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5594 if (!p->texture_refraction)
5595 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);
5596 if (!p->texture_refraction)
5599 else if (p->materialflags & MATERIALFLAG_CAMERA)
5601 if (!p->texture_camera)
5602 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);
5603 if (!p->texture_camera)
5607 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5609 if (!p->texture_reflection)
5610 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);
5611 if (!p->texture_reflection)
5617 r_refdef.view = originalview;
5618 r_refdef.view.showdebug = false;
5619 r_refdef.view.width = r_waterstate.waterwidth;
5620 r_refdef.view.height = r_waterstate.waterheight;
5621 r_refdef.view.useclipplane = true;
5622 myview = r_refdef.view;
5623 r_waterstate.renderingscene = true;
5624 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5626 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5628 r_refdef.view = myview;
5629 if(r_water_scissormode.integer)
5632 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5633 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5636 // render reflected scene and copy into texture
5637 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5638 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5639 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5640 r_refdef.view.clipplane = p->plane;
5642 // reverse the cullface settings for this render
5643 r_refdef.view.cullface_front = GL_FRONT;
5644 r_refdef.view.cullface_back = GL_BACK;
5645 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5647 r_refdef.view.usecustompvs = true;
5649 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5651 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5654 R_ResetViewRendering3D();
5655 R_ClearScreen(r_refdef.fogenabled);
5656 if(r_water_scissormode.integer & 2)
5657 R_View_UpdateWithScissor(myscissor);
5660 if(r_water_scissormode.integer & 1)
5661 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5664 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);
5667 // render the normal view scene and copy into texture
5668 // (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)
5669 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5671 r_refdef.view = myview;
5672 if(r_water_scissormode.integer)
5675 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5676 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5679 r_waterstate.renderingrefraction = true;
5681 r_refdef.view.clipplane = p->plane;
5682 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5683 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5685 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5687 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5688 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5689 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5690 R_RenderView_UpdateViewVectors();
5691 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5693 r_refdef.view.usecustompvs = true;
5694 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);
5698 PlaneClassify(&r_refdef.view.clipplane);
5700 R_ResetViewRendering3D();
5701 R_ClearScreen(r_refdef.fogenabled);
5702 if(r_water_scissormode.integer & 2)
5703 R_View_UpdateWithScissor(myscissor);
5706 if(r_water_scissormode.integer & 1)
5707 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5710 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);
5711 r_waterstate.renderingrefraction = false;
5713 else if (p->materialflags & MATERIALFLAG_CAMERA)
5715 r_refdef.view = myview;
5717 r_refdef.view.clipplane = p->plane;
5718 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5719 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5721 r_refdef.view.width = r_waterstate.camerawidth;
5722 r_refdef.view.height = r_waterstate.cameraheight;
5723 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5724 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5726 if(p->camera_entity)
5728 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5729 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5732 // note: all of the view is used for displaying... so
5733 // there is no use in scissoring
5735 // reverse the cullface settings for this render
5736 r_refdef.view.cullface_front = GL_FRONT;
5737 r_refdef.view.cullface_back = GL_BACK;
5738 // also reverse the view matrix
5739 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
5740 R_RenderView_UpdateViewVectors();
5741 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5743 r_refdef.view.usecustompvs = true;
5744 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);
5747 // camera needs no clipplane
5748 r_refdef.view.useclipplane = false;
5750 PlaneClassify(&r_refdef.view.clipplane);
5752 R_ResetViewRendering3D();
5753 R_ClearScreen(r_refdef.fogenabled);
5757 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);
5758 r_waterstate.renderingrefraction = false;
5762 if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5763 r_waterstate.renderingscene = false;
5764 r_refdef.view = originalview;
5765 R_ResetViewRendering3D();
5766 R_ClearScreen(r_refdef.fogenabled);
5770 r_refdef.view = originalview;
5771 r_waterstate.renderingscene = false;
5772 Cvar_SetValueQuick(&r_water, 0);
5773 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
5775 // lowquality hack, restore cvars
5776 if (qualityreduction > 0)
5778 if (qualityreduction >= 1)
5780 Cvar_SetValueQuick(&r_shadows, old_r_shadows);
5781 Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
5782 Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
5784 if (qualityreduction >= 2)
5786 Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
5787 Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
5788 Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
5793 void R_Bloom_StartFrame(void)
5795 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5796 int viewwidth, viewheight;
5799 if (r_viewscale_fpsscaling.integer)
5801 double actualframetime;
5802 double targetframetime;
5804 actualframetime = r_refdef.lastdrawscreentime;
5805 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5806 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5807 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5808 if (r_viewscale_fpsscaling_stepsize.value > 0)
5809 adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5810 viewscalefpsadjusted += adjust;
5811 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5814 viewscalefpsadjusted = 1.0f;
5816 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5818 switch(vid.renderpath)
5820 case RENDERPATH_GL20:
5821 case RENDERPATH_D3D9:
5822 case RENDERPATH_D3D10:
5823 case RENDERPATH_D3D11:
5824 case RENDERPATH_SOFT:
5825 case RENDERPATH_GLES2:
5827 case RENDERPATH_GL11:
5828 case RENDERPATH_GL13:
5829 case RENDERPATH_GLES1:
5833 // set bloomwidth and bloomheight to the bloom resolution that will be
5834 // used (often less than the screen resolution for faster rendering)
5835 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5836 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5837 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5838 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5839 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5841 // calculate desired texture sizes
5842 if (vid.support.arb_texture_non_power_of_two)
5844 screentexturewidth = vid.width;
5845 screentextureheight = vid.height;
5846 bloomtexturewidth = r_bloomstate.bloomwidth;
5847 bloomtextureheight = r_bloomstate.bloomheight;
5851 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
5852 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
5853 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
5854 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
5857 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))
5859 Cvar_SetValueQuick(&r_hdr, 0);
5860 Cvar_SetValueQuick(&r_bloom, 0);
5861 Cvar_SetValueQuick(&r_motionblur, 0);
5862 Cvar_SetValueQuick(&r_damageblur, 0);
5865 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)
5866 screentexturewidth = screentextureheight = 0;
5867 if (!r_hdr.integer && !r_bloom.integer)
5868 bloomtexturewidth = bloomtextureheight = 0;
5870 textype = TEXTYPE_COLORBUFFER;
5871 switch (vid.renderpath)
5873 case RENDERPATH_GL20:
5874 case RENDERPATH_GLES2:
5875 if (vid.support.ext_framebuffer_object)
5877 if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5878 if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5881 case RENDERPATH_GL11:
5882 case RENDERPATH_GL13:
5883 case RENDERPATH_GLES1:
5884 case RENDERPATH_D3D9:
5885 case RENDERPATH_D3D10:
5886 case RENDERPATH_D3D11:
5887 case RENDERPATH_SOFT:
5891 // allocate textures as needed
5892 if (r_bloomstate.screentexturewidth != screentexturewidth
5893 || r_bloomstate.screentextureheight != screentextureheight
5894 || r_bloomstate.bloomtexturewidth != bloomtexturewidth
5895 || r_bloomstate.bloomtextureheight != bloomtextureheight
5896 || r_bloomstate.texturetype != textype
5897 || r_bloomstate.viewfbo != r_viewfbo.integer)
5899 if (r_bloomstate.texture_bloom)
5900 R_FreeTexture(r_bloomstate.texture_bloom);
5901 r_bloomstate.texture_bloom = NULL;
5902 if (r_bloomstate.texture_screen)
5903 R_FreeTexture(r_bloomstate.texture_screen);
5904 r_bloomstate.texture_screen = NULL;
5905 if (r_bloomstate.fbo_framebuffer)
5906 R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
5907 r_bloomstate.fbo_framebuffer = 0;
5908 if (r_bloomstate.texture_framebuffercolor)
5909 R_FreeTexture(r_bloomstate.texture_framebuffercolor);
5910 r_bloomstate.texture_framebuffercolor = NULL;
5911 if (r_bloomstate.texture_framebufferdepth)
5912 R_FreeTexture(r_bloomstate.texture_framebufferdepth);
5913 r_bloomstate.texture_framebufferdepth = NULL;
5914 r_bloomstate.screentexturewidth = screentexturewidth;
5915 r_bloomstate.screentextureheight = screentextureheight;
5916 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5917 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);
5918 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
5920 // FIXME: choose depth bits based on a cvar
5921 r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
5922 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);
5923 r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5924 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5925 // render depth into one texture and normalmap into the other
5929 qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5930 qglReadBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5931 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
5932 if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
5933 Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
5936 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5937 r_bloomstate.bloomtextureheight = bloomtextureheight;
5938 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5939 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);
5940 r_bloomstate.viewfbo = r_viewfbo.integer;
5941 r_bloomstate.texturetype = textype;
5944 // when doing a reduced render (HDR) we want to use a smaller area
5945 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5946 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5947 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5948 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5949 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5951 // set up a texcoord array for the full resolution screen image
5952 // (we have to keep this around to copy back during final render)
5953 r_bloomstate.screentexcoord2f[0] = 0;
5954 r_bloomstate.screentexcoord2f[1] = (float)viewheight / (float)r_bloomstate.screentextureheight;
5955 r_bloomstate.screentexcoord2f[2] = (float)viewwidth / (float)r_bloomstate.screentexturewidth;
5956 r_bloomstate.screentexcoord2f[3] = (float)viewheight / (float)r_bloomstate.screentextureheight;
5957 r_bloomstate.screentexcoord2f[4] = (float)viewwidth / (float)r_bloomstate.screentexturewidth;
5958 r_bloomstate.screentexcoord2f[5] = 0;
5959 r_bloomstate.screentexcoord2f[6] = 0;
5960 r_bloomstate.screentexcoord2f[7] = 0;
5962 // set up a texcoord array for the reduced resolution bloom image
5963 // (which will be additive blended over the screen image)
5964 r_bloomstate.bloomtexcoord2f[0] = 0;
5965 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5966 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5967 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5968 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5969 r_bloomstate.bloomtexcoord2f[5] = 0;
5970 r_bloomstate.bloomtexcoord2f[6] = 0;
5971 r_bloomstate.bloomtexcoord2f[7] = 0;
5973 switch(vid.renderpath)
5975 case RENDERPATH_GL11:
5976 case RENDERPATH_GL13:
5977 case RENDERPATH_GL20:
5978 case RENDERPATH_SOFT:
5979 case RENDERPATH_GLES1:
5980 case RENDERPATH_GLES2:
5982 case RENDERPATH_D3D9:
5983 case RENDERPATH_D3D10:
5984 case RENDERPATH_D3D11:
5987 for (i = 0;i < 4;i++)
5989 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
5990 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
5991 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
5992 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
5998 if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth)
6000 r_bloomstate.enabled = true;
6001 r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer;
6004 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);
6006 if (r_bloomstate.fbo_framebuffer)
6007 r_refdef.view.clear = true;
6010 void R_Bloom_CopyBloomTexture(float colorscale)
6012 r_refdef.stats.bloom++;
6014 // scale down screen texture to the bloom texture size
6016 R_Mesh_SetMainRenderTargets();
6017 R_SetViewport(&r_bloomstate.viewport);
6018 GL_BlendFunc(GL_ONE, GL_ZERO);
6019 GL_Color(colorscale, colorscale, colorscale, 1);
6020 // 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...
6021 switch(vid.renderpath)
6023 case RENDERPATH_GL11:
6024 case RENDERPATH_GL13:
6025 case RENDERPATH_GL20:
6026 case RENDERPATH_GLES1:
6027 case RENDERPATH_GLES2:
6028 case RENDERPATH_SOFT:
6029 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6031 case RENDERPATH_D3D9:
6032 case RENDERPATH_D3D10:
6033 case RENDERPATH_D3D11:
6034 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6037 // TODO: do boxfilter scale-down in shader?
6038 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6039 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6040 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6042 // we now have a bloom image in the framebuffer
6043 // copy it into the bloom image texture for later processing
6044 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);
6045 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6048 void R_Bloom_CopyHDRTexture(void)
6050 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);
6051 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6054 void R_Bloom_MakeTexture(void)
6057 float xoffset, yoffset, r, brighten;
6059 r_refdef.stats.bloom++;
6061 R_ResetViewRendering2D();
6063 // we have a bloom image in the framebuffer
6065 R_SetViewport(&r_bloomstate.viewport);
6067 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6070 r = bound(0, r_bloom_colorexponent.value / x, 1);
6071 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6073 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
6074 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
6075 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6076 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6078 // copy the vertically blurred bloom view to a texture
6079 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);
6080 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6083 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
6084 brighten = r_bloom_brighten.value;
6085 if (r_bloomstate.hdr)
6086 brighten *= r_hdr_range.value;
6087 brighten = sqrt(brighten);
6089 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6090 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
6092 for (dir = 0;dir < 2;dir++)
6094 // blend on at multiple vertical offsets to achieve a vertical blur
6095 // TODO: do offset blends using GLSL
6096 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6097 GL_BlendFunc(GL_ONE, GL_ZERO);
6098 for (x = -range;x <= range;x++)
6100 if (!dir){xoffset = 0;yoffset = x;}
6101 else {xoffset = x;yoffset = 0;}
6102 xoffset /= (float)r_bloomstate.bloomtexturewidth;
6103 yoffset /= (float)r_bloomstate.bloomtextureheight;
6104 // compute a texcoord array with the specified x and y offset
6105 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
6106 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6107 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6108 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6109 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6110 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
6111 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
6112 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
6113 // this r value looks like a 'dot' particle, fading sharply to
6114 // black at the edges
6115 // (probably not realistic but looks good enough)
6116 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6117 //r = brighten/(range*2+1);
6118 r = brighten / (range * 2 + 1);
6120 r *= (1 - x*x/(float)(range*range));
6121 GL_Color(r, r, r, 1);
6122 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6123 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6124 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6125 GL_BlendFunc(GL_ONE, GL_ONE);
6128 // copy the vertically blurred bloom view to a texture
6129 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);
6130 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6134 void R_HDR_RenderBloomTexture(void)
6136 int oldwidth, oldheight;
6137 float oldcolorscale;
6138 qboolean oldwaterstate;
6140 oldwaterstate = r_waterstate.enabled;
6141 oldcolorscale = r_refdef.view.colorscale;
6142 oldwidth = r_refdef.view.width;
6143 oldheight = r_refdef.view.height;
6144 r_refdef.view.width = r_bloomstate.bloomwidth;
6145 r_refdef.view.height = r_bloomstate.bloomheight;
6147 if(r_hdr.integer < 2)
6148 r_waterstate.enabled = false;
6150 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
6151 // TODO: add exposure compensation features
6152 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6154 r_refdef.view.showdebug = false;
6155 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6157 R_ResetViewRendering3D();
6159 R_ClearScreen(r_refdef.fogenabled);
6160 if (r_timereport_active)
6161 R_TimeReport("HDRclear");
6164 if (r_timereport_active)
6165 R_TimeReport("visibility");
6167 // only do secondary renders with HDR if r_hdr is 2 or higher
6168 r_waterstate.numwaterplanes = 0;
6169 if (r_waterstate.enabled)
6170 R_RenderWaterPlanes();
6172 r_refdef.view.showdebug = true;
6174 r_waterstate.numwaterplanes = 0;
6176 R_ResetViewRendering2D();
6178 R_Bloom_CopyHDRTexture();
6179 R_Bloom_MakeTexture();
6181 // restore the view settings
6182 r_waterstate.enabled = oldwaterstate;
6183 r_refdef.view.width = oldwidth;
6184 r_refdef.view.height = oldheight;
6185 r_refdef.view.colorscale = oldcolorscale;
6187 R_ResetViewRendering3D();
6189 R_ClearScreen(r_refdef.fogenabled);
6190 if (r_timereport_active)
6191 R_TimeReport("viewclear");
6194 static void R_BlendView(void)
6196 unsigned int permutation;
6197 float uservecs[4][4];
6199 switch (vid.renderpath)
6201 case RENDERPATH_GL20:
6202 case RENDERPATH_D3D9:
6203 case RENDERPATH_D3D10:
6204 case RENDERPATH_D3D11:
6205 case RENDERPATH_SOFT:
6206 case RENDERPATH_GLES2:
6208 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6209 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6210 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6211 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6212 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6214 if (r_bloomstate.texture_screen)
6216 // make sure the buffer is available
6217 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6219 R_ResetViewRendering2D();
6220 R_Mesh_SetMainRenderTargets();
6222 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6224 // declare variables
6226 static float avgspeed;
6228 speed = VectorLength(cl.movement_velocity);
6230 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
6231 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
6233 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
6234 speed = bound(0, speed, 1);
6235 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
6237 // calculate values into a standard alpha
6238 cl.motionbluralpha = 1 - exp(-
6240 (r_motionblur.value * speed / 80)
6242 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6245 max(0.0001, cl.time - cl.oldtime) // fps independent
6248 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6249 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6251 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6253 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6254 GL_Color(1, 1, 1, cl.motionbluralpha);
6255 switch(vid.renderpath)
6257 case RENDERPATH_GL11:
6258 case RENDERPATH_GL13:
6259 case RENDERPATH_GL20:
6260 case RENDERPATH_GLES1:
6261 case RENDERPATH_GLES2:
6262 case RENDERPATH_SOFT:
6263 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6265 case RENDERPATH_D3D9:
6266 case RENDERPATH_D3D10:
6267 case RENDERPATH_D3D11:
6268 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6271 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6272 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6273 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6277 // copy view into the screen texture
6278 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);
6279 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6281 else if (!r_bloomstate.texture_bloom)
6283 // we may still have to do view tint...
6284 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6286 // apply a color tint to the whole view
6287 R_ResetViewRendering2D();
6288 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6289 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6290 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6291 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6292 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6294 break; // no screen processing, no bloom, skip it
6297 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6299 // render simple bloom effect
6300 // copy the screen and shrink it and darken it for the bloom process
6301 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6302 // make the bloom texture
6303 R_Bloom_MakeTexture();
6306 #if _MSC_VER >= 1400
6307 #define sscanf sscanf_s
6309 memset(uservecs, 0, sizeof(uservecs));
6310 if (r_glsl_postprocess_uservec1_enable.integer)
6311 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6312 if (r_glsl_postprocess_uservec2_enable.integer)
6313 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6314 if (r_glsl_postprocess_uservec3_enable.integer)
6315 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6316 if (r_glsl_postprocess_uservec4_enable.integer)
6317 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6319 R_ResetViewRendering2D();
6320 GL_Color(1, 1, 1, 1);
6321 GL_BlendFunc(GL_ONE, GL_ZERO);
6323 switch(vid.renderpath)
6325 case RENDERPATH_GL20:
6326 case RENDERPATH_GLES2:
6327 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6328 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6329 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_bloomstate.texture_screen);
6330 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_bloomstate.texture_bloom );
6331 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6332 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]);
6333 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6334 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]);
6335 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]);
6336 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]);
6337 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]);
6338 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6339 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6340 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);
6342 case RENDERPATH_D3D9:
6344 // 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...
6345 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6346 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6347 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6348 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6349 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6350 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6351 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6352 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6353 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6354 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6355 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6356 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6357 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6358 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6361 case RENDERPATH_D3D10:
6362 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6364 case RENDERPATH_D3D11:
6365 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6367 case RENDERPATH_SOFT:
6368 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6369 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6370 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6371 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6372 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6373 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6374 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6375 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6376 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6377 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6378 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6379 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6380 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6381 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6386 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6387 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6389 case RENDERPATH_GL11:
6390 case RENDERPATH_GL13:
6391 case RENDERPATH_GLES1:
6392 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6394 // apply a color tint to the whole view
6395 R_ResetViewRendering2D();
6396 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6397 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6398 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6399 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6400 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6406 matrix4x4_t r_waterscrollmatrix;
6408 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6410 if (r_refdef.fog_density)
6412 r_refdef.fogcolor[0] = r_refdef.fog_red;
6413 r_refdef.fogcolor[1] = r_refdef.fog_green;
6414 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6416 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6417 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6418 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6419 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6423 VectorCopy(r_refdef.fogcolor, fogvec);
6424 // color.rgb *= ContrastBoost * SceneBrightness;
6425 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6426 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6427 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6428 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6433 void R_UpdateVariables(void)
6437 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6439 r_refdef.farclip = r_farclip_base.value;
6440 if (r_refdef.scene.worldmodel)
6441 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6442 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6444 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6445 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6446 r_refdef.polygonfactor = 0;
6447 r_refdef.polygonoffset = 0;
6448 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6449 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6451 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6452 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6453 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6454 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6455 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6456 if (FAKELIGHT_ENABLED)
6458 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6460 if (r_showsurfaces.integer)
6462 r_refdef.scene.rtworld = false;
6463 r_refdef.scene.rtworldshadows = false;
6464 r_refdef.scene.rtdlight = false;
6465 r_refdef.scene.rtdlightshadows = false;
6466 r_refdef.lightmapintensity = 0;
6469 if (gamemode == GAME_NEHAHRA)
6471 if (gl_fogenable.integer)
6473 r_refdef.oldgl_fogenable = true;
6474 r_refdef.fog_density = gl_fogdensity.value;
6475 r_refdef.fog_red = gl_fogred.value;
6476 r_refdef.fog_green = gl_foggreen.value;
6477 r_refdef.fog_blue = gl_fogblue.value;
6478 r_refdef.fog_alpha = 1;
6479 r_refdef.fog_start = 0;
6480 r_refdef.fog_end = gl_skyclip.value;
6481 r_refdef.fog_height = 1<<30;
6482 r_refdef.fog_fadedepth = 128;
6484 else if (r_refdef.oldgl_fogenable)
6486 r_refdef.oldgl_fogenable = false;
6487 r_refdef.fog_density = 0;
6488 r_refdef.fog_red = 0;
6489 r_refdef.fog_green = 0;
6490 r_refdef.fog_blue = 0;
6491 r_refdef.fog_alpha = 0;
6492 r_refdef.fog_start = 0;
6493 r_refdef.fog_end = 0;
6494 r_refdef.fog_height = 1<<30;
6495 r_refdef.fog_fadedepth = 128;
6499 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6500 r_refdef.fog_start = max(0, r_refdef.fog_start);
6501 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6503 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6505 if (r_refdef.fog_density && r_drawfog.integer)
6507 r_refdef.fogenabled = true;
6508 // this is the point where the fog reaches 0.9986 alpha, which we
6509 // consider a good enough cutoff point for the texture
6510 // (0.9986 * 256 == 255.6)
6511 if (r_fog_exp2.integer)
6512 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6514 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6515 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6516 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6517 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6518 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6519 R_BuildFogHeightTexture();
6520 // fog color was already set
6521 // update the fog texture
6522 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)
6523 R_BuildFogTexture();
6524 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6525 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6528 r_refdef.fogenabled = false;
6530 switch(vid.renderpath)
6532 case RENDERPATH_GL20:
6533 case RENDERPATH_D3D9:
6534 case RENDERPATH_D3D10:
6535 case RENDERPATH_D3D11:
6536 case RENDERPATH_SOFT:
6537 case RENDERPATH_GLES2:
6538 if(v_glslgamma.integer && !vid_gammatables_trivial)
6540 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6542 // build GLSL gamma texture
6543 #define RAMPWIDTH 256
6544 unsigned short ramp[RAMPWIDTH * 3];
6545 unsigned char rampbgr[RAMPWIDTH][4];
6548 r_texture_gammaramps_serial = vid_gammatables_serial;
6550 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6551 for(i = 0; i < RAMPWIDTH; ++i)
6553 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6554 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6555 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6558 if (r_texture_gammaramps)
6560 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6564 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6570 // remove GLSL gamma texture
6573 case RENDERPATH_GL11:
6574 case RENDERPATH_GL13:
6575 case RENDERPATH_GLES1:
6580 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6581 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6587 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6588 if( scenetype != r_currentscenetype ) {
6589 // store the old scenetype
6590 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6591 r_currentscenetype = scenetype;
6592 // move in the new scene
6593 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6602 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6604 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6605 if( scenetype == r_currentscenetype ) {
6606 return &r_refdef.scene;
6608 return &r_scenes_store[ scenetype ];
6617 int dpsoftrast_test;
6618 void R_RenderView(void)
6620 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6622 dpsoftrast_test = r_test.integer;
6624 if (r_timereport_active)
6625 R_TimeReport("start");
6626 r_textureframe++; // used only by R_GetCurrentTexture
6627 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6629 if(R_CompileShader_CheckStaticParms())
6632 if (!r_drawentities.integer)
6633 r_refdef.scene.numentities = 0;
6635 R_AnimCache_ClearCache();
6636 R_FrameData_NewFrame();
6638 /* adjust for stereo display */
6639 if(R_Stereo_Active())
6641 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);
6642 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6645 if (r_refdef.view.isoverlay)
6647 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6648 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6649 R_TimeReport("depthclear");
6651 r_refdef.view.showdebug = false;
6653 r_waterstate.enabled = false;
6654 r_waterstate.numwaterplanes = 0;
6658 r_refdef.view.matrix = originalmatrix;
6664 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6666 r_refdef.view.matrix = originalmatrix;
6667 return; //Host_Error ("R_RenderView: NULL worldmodel");
6670 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6672 R_RenderView_UpdateViewVectors();
6674 R_Shadow_UpdateWorldLightSelection();
6676 R_Bloom_StartFrame();
6677 R_Water_StartFrame();
6680 if (r_timereport_active)
6681 R_TimeReport("viewsetup");
6683 R_ResetViewRendering3D();
6685 if (r_refdef.view.clear || r_refdef.fogenabled)
6687 R_ClearScreen(r_refdef.fogenabled);
6688 if (r_timereport_active)
6689 R_TimeReport("viewclear");
6691 r_refdef.view.clear = true;
6693 // this produces a bloom texture to be used in R_BlendView() later
6694 if (r_bloomstate.hdr)
6696 R_HDR_RenderBloomTexture();
6697 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6698 r_textureframe++; // used only by R_GetCurrentTexture
6701 r_refdef.view.showdebug = true;
6704 if (r_timereport_active)
6705 R_TimeReport("visibility");
6707 r_waterstate.numwaterplanes = 0;
6708 if (r_waterstate.enabled)
6709 R_RenderWaterPlanes();
6712 r_waterstate.numwaterplanes = 0;
6715 if (r_timereport_active)
6716 R_TimeReport("blendview");
6718 GL_Scissor(0, 0, vid.width, vid.height);
6719 GL_ScissorTest(false);
6721 r_refdef.view.matrix = originalmatrix;
6726 void R_RenderWaterPlanes(void)
6728 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6730 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6731 if (r_timereport_active)
6732 R_TimeReport("waterworld");
6735 // don't let sound skip if going slow
6736 if (r_refdef.scene.extraupdate)
6739 R_DrawModelsAddWaterPlanes();
6740 if (r_timereport_active)
6741 R_TimeReport("watermodels");
6743 if (r_waterstate.numwaterplanes)
6745 R_Water_ProcessPlanes();
6746 if (r_timereport_active)
6747 R_TimeReport("waterscenes");
6751 extern void R_DrawLightningBeams (void);
6752 extern void VM_CL_AddPolygonsToMeshQueue (void);
6753 extern void R_DrawPortals (void);
6754 extern cvar_t cl_locs_show;
6755 static void R_DrawLocs(void);
6756 static void R_DrawEntityBBoxes(void);
6757 static void R_DrawModelDecals(void);
6758 extern void R_DrawModelShadows(void);
6759 extern void R_DrawModelShadowMaps(void);
6760 extern cvar_t cl_decals_newsystem;
6761 extern qboolean r_shadow_usingdeferredprepass;
6762 void R_RenderScene(void)
6764 qboolean shadowmapping = false;
6766 if (r_timereport_active)
6767 R_TimeReport("beginscene");
6769 r_refdef.stats.renders++;
6773 // don't let sound skip if going slow
6774 if (r_refdef.scene.extraupdate)
6777 R_MeshQueue_BeginScene();
6781 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);
6783 if (r_timereport_active)
6784 R_TimeReport("skystartframe");
6786 if (cl.csqc_vidvars.drawworld)
6788 // don't let sound skip if going slow
6789 if (r_refdef.scene.extraupdate)
6792 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6794 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6795 if (r_timereport_active)
6796 R_TimeReport("worldsky");
6799 if (R_DrawBrushModelsSky() && r_timereport_active)
6800 R_TimeReport("bmodelsky");
6802 if (skyrendermasked && skyrenderlater)
6804 // we have to force off the water clipping plane while rendering sky
6808 if (r_timereport_active)
6809 R_TimeReport("sky");
6813 R_AnimCache_CacheVisibleEntities();
6814 if (r_timereport_active)
6815 R_TimeReport("animation");
6817 R_Shadow_PrepareLights();
6818 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6819 R_Shadow_PrepareModelShadows();
6820 if (r_timereport_active)
6821 R_TimeReport("preparelights");
6823 if (R_Shadow_ShadowMappingEnabled())
6824 shadowmapping = true;
6826 if (r_shadow_usingdeferredprepass)
6827 R_Shadow_DrawPrepass();
6829 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6831 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6832 if (r_timereport_active)
6833 R_TimeReport("worlddepth");
6835 if (r_depthfirst.integer >= 2)
6837 R_DrawModelsDepth();
6838 if (r_timereport_active)
6839 R_TimeReport("modeldepth");
6842 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6844 R_DrawModelShadowMaps();
6845 R_ResetViewRendering3D();
6846 // don't let sound skip if going slow
6847 if (r_refdef.scene.extraupdate)
6851 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6853 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6854 if (r_timereport_active)
6855 R_TimeReport("world");
6858 // don't let sound skip if going slow
6859 if (r_refdef.scene.extraupdate)
6863 if (r_timereport_active)
6864 R_TimeReport("models");
6866 // don't let sound skip if going slow
6867 if (r_refdef.scene.extraupdate)
6870 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6872 R_DrawModelShadows();
6873 R_ResetViewRendering3D();
6874 // don't let sound skip if going slow
6875 if (r_refdef.scene.extraupdate)
6879 if (!r_shadow_usingdeferredprepass)
6881 R_Shadow_DrawLights();
6882 if (r_timereport_active)
6883 R_TimeReport("rtlights");
6886 // don't let sound skip if going slow
6887 if (r_refdef.scene.extraupdate)
6890 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6892 R_DrawModelShadows();
6893 R_ResetViewRendering3D();
6894 // don't let sound skip if going slow
6895 if (r_refdef.scene.extraupdate)
6899 if (cl.csqc_vidvars.drawworld)
6901 if (cl_decals_newsystem.integer)
6903 R_DrawModelDecals();
6904 if (r_timereport_active)
6905 R_TimeReport("modeldecals");
6910 if (r_timereport_active)
6911 R_TimeReport("decals");
6915 if (r_timereport_active)
6916 R_TimeReport("particles");
6919 if (r_timereport_active)
6920 R_TimeReport("explosions");
6922 R_DrawLightningBeams();
6923 if (r_timereport_active)
6924 R_TimeReport("lightning");
6927 VM_CL_AddPolygonsToMeshQueue();
6929 if (r_refdef.view.showdebug)
6931 if (cl_locs_show.integer)
6934 if (r_timereport_active)
6935 R_TimeReport("showlocs");
6938 if (r_drawportals.integer)
6941 if (r_timereport_active)
6942 R_TimeReport("portals");
6945 if (r_showbboxes.value > 0)
6947 R_DrawEntityBBoxes();
6948 if (r_timereport_active)
6949 R_TimeReport("bboxes");
6953 if (r_transparent.integer)
6955 R_MeshQueue_RenderTransparent();
6956 if (r_timereport_active)
6957 R_TimeReport("drawtrans");
6960 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))
6962 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6963 if (r_timereport_active)
6964 R_TimeReport("worlddebug");
6965 R_DrawModelsDebug();
6966 if (r_timereport_active)
6967 R_TimeReport("modeldebug");
6970 if (cl.csqc_vidvars.drawworld)
6972 R_Shadow_DrawCoronas();
6973 if (r_timereport_active)
6974 R_TimeReport("coronas");
6979 GL_DepthTest(false);
6980 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6981 GL_Color(1, 1, 1, 1);
6982 qglBegin(GL_POLYGON);
6983 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6984 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6985 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6986 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
6988 qglBegin(GL_POLYGON);
6989 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]);
6990 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]);
6991 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]);
6992 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]);
6994 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
6998 // don't let sound skip if going slow
6999 if (r_refdef.scene.extraupdate)
7002 R_ResetViewRendering2D();
7005 static const unsigned short bboxelements[36] =
7015 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7018 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7020 RSurf_ActiveWorldEntity();
7022 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7023 GL_DepthMask(false);
7024 GL_DepthRange(0, 1);
7025 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7026 // R_Mesh_ResetTextureState();
7028 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7029 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7030 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7031 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7032 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7033 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7034 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7035 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7036 R_FillColors(color4f, 8, cr, cg, cb, ca);
7037 if (r_refdef.fogenabled)
7039 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7041 f1 = RSurf_FogVertex(v);
7043 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7044 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7045 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7048 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7049 R_Mesh_ResetTextureState();
7050 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7051 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7054 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7058 prvm_edict_t *edict;
7059 prvm_prog_t *prog_save = prog;
7061 // this function draws bounding boxes of server entities
7065 GL_CullFace(GL_NONE);
7066 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7070 for (i = 0;i < numsurfaces;i++)
7072 edict = PRVM_EDICT_NUM(surfacelist[i]);
7073 switch ((int)edict->fields.server->solid)
7075 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
7076 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
7077 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
7078 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7079 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
7080 default: Vector4Set(color, 0, 0, 0, 0.50);break;
7082 color[3] *= r_showbboxes.value;
7083 color[3] = bound(0, color[3], 1);
7084 GL_DepthTest(!r_showdisabledepthtest.integer);
7085 GL_CullFace(r_refdef.view.cullface_front);
7086 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7092 static void R_DrawEntityBBoxes(void)
7095 prvm_edict_t *edict;
7097 prvm_prog_t *prog_save = prog;
7099 // this function draws bounding boxes of server entities
7105 for (i = 0;i < prog->num_edicts;i++)
7107 edict = PRVM_EDICT_NUM(i);
7108 if (edict->priv.server->free)
7110 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7111 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7113 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7115 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7116 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7122 static const int nomodelelement3i[24] =
7134 static const unsigned short nomodelelement3s[24] =
7146 static const float nomodelvertex3f[6*3] =
7156 static const float nomodelcolor4f[6*4] =
7158 0.0f, 0.0f, 0.5f, 1.0f,
7159 0.0f, 0.0f, 0.5f, 1.0f,
7160 0.0f, 0.5f, 0.0f, 1.0f,
7161 0.0f, 0.5f, 0.0f, 1.0f,
7162 0.5f, 0.0f, 0.0f, 1.0f,
7163 0.5f, 0.0f, 0.0f, 1.0f
7166 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7172 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);
7174 // this is only called once per entity so numsurfaces is always 1, and
7175 // surfacelist is always {0}, so this code does not handle batches
7177 if (rsurface.ent_flags & RENDER_ADDITIVE)
7179 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7180 GL_DepthMask(false);
7182 else if (rsurface.colormod[3] < 1)
7184 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7185 GL_DepthMask(false);
7189 GL_BlendFunc(GL_ONE, GL_ZERO);
7192 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7193 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7194 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7195 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7196 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7197 for (i = 0, c = color4f;i < 6;i++, c += 4)
7199 c[0] *= rsurface.colormod[0];
7200 c[1] *= rsurface.colormod[1];
7201 c[2] *= rsurface.colormod[2];
7202 c[3] *= rsurface.colormod[3];
7204 if (r_refdef.fogenabled)
7206 for (i = 0, c = color4f;i < 6;i++, c += 4)
7208 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7210 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7211 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7212 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7215 // R_Mesh_ResetTextureState();
7216 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7217 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7218 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7221 void R_DrawNoModel(entity_render_t *ent)
7224 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7225 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7226 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7228 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7231 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7233 vec3_t right1, right2, diff, normal;
7235 VectorSubtract (org2, org1, normal);
7237 // calculate 'right' vector for start
7238 VectorSubtract (r_refdef.view.origin, org1, diff);
7239 CrossProduct (normal, diff, right1);
7240 VectorNormalize (right1);
7242 // calculate 'right' vector for end
7243 VectorSubtract (r_refdef.view.origin, org2, diff);
7244 CrossProduct (normal, diff, right2);
7245 VectorNormalize (right2);
7247 vert[ 0] = org1[0] + width * right1[0];
7248 vert[ 1] = org1[1] + width * right1[1];
7249 vert[ 2] = org1[2] + width * right1[2];
7250 vert[ 3] = org1[0] - width * right1[0];
7251 vert[ 4] = org1[1] - width * right1[1];
7252 vert[ 5] = org1[2] - width * right1[2];
7253 vert[ 6] = org2[0] - width * right2[0];
7254 vert[ 7] = org2[1] - width * right2[1];
7255 vert[ 8] = org2[2] - width * right2[2];
7256 vert[ 9] = org2[0] + width * right2[0];
7257 vert[10] = org2[1] + width * right2[1];
7258 vert[11] = org2[2] + width * right2[2];
7261 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)
7263 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7264 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7265 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7266 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7267 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7268 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7269 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7270 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7271 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7272 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7273 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7274 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7277 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7282 VectorSet(v, x, y, z);
7283 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7284 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7286 if (i == mesh->numvertices)
7288 if (mesh->numvertices < mesh->maxvertices)
7290 VectorCopy(v, vertex3f);
7291 mesh->numvertices++;
7293 return mesh->numvertices;
7299 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7303 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7304 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7305 e = mesh->element3i + mesh->numtriangles * 3;
7306 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7308 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7309 if (mesh->numtriangles < mesh->maxtriangles)
7314 mesh->numtriangles++;
7316 element[1] = element[2];
7320 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7324 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7325 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7326 e = mesh->element3i + mesh->numtriangles * 3;
7327 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7329 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7330 if (mesh->numtriangles < mesh->maxtriangles)
7335 mesh->numtriangles++;
7337 element[1] = element[2];
7341 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7342 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7344 int planenum, planenum2;
7347 mplane_t *plane, *plane2;
7349 double temppoints[2][256*3];
7350 // figure out how large a bounding box we need to properly compute this brush
7352 for (w = 0;w < numplanes;w++)
7353 maxdist = max(maxdist, fabs(planes[w].dist));
7354 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7355 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7356 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7360 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7361 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7363 if (planenum2 == planenum)
7365 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);
7368 if (tempnumpoints < 3)
7370 // generate elements forming a triangle fan for this polygon
7371 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7375 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)
7377 texturelayer_t *layer;
7378 layer = t->currentlayers + t->currentnumlayers++;
7380 layer->depthmask = depthmask;
7381 layer->blendfunc1 = blendfunc1;
7382 layer->blendfunc2 = blendfunc2;
7383 layer->texture = texture;
7384 layer->texmatrix = *matrix;
7385 layer->color[0] = r;
7386 layer->color[1] = g;
7387 layer->color[2] = b;
7388 layer->color[3] = a;
7391 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7393 if(parms[0] == 0 && parms[1] == 0)
7395 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7396 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7401 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7404 index = parms[2] + r_refdef.scene.time * parms[3];
7405 index -= floor(index);
7406 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7409 case Q3WAVEFUNC_NONE:
7410 case Q3WAVEFUNC_NOISE:
7411 case Q3WAVEFUNC_COUNT:
7414 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7415 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7416 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7417 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7418 case Q3WAVEFUNC_TRIANGLE:
7420 f = index - floor(index);
7431 f = parms[0] + parms[1] * f;
7432 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7433 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7437 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7442 matrix4x4_t matrix, temp;
7443 switch(tcmod->tcmod)
7447 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7448 matrix = r_waterscrollmatrix;
7450 matrix = identitymatrix;
7452 case Q3TCMOD_ENTITYTRANSLATE:
7453 // this is used in Q3 to allow the gamecode to control texcoord
7454 // scrolling on the entity, which is not supported in darkplaces yet.
7455 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7457 case Q3TCMOD_ROTATE:
7458 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7459 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
7460 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7463 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7465 case Q3TCMOD_SCROLL:
7466 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
7468 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7469 w = (int) tcmod->parms[0];
7470 h = (int) tcmod->parms[1];
7471 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
7473 idx = (int) floor(f * w * h);
7474 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7476 case Q3TCMOD_STRETCH:
7477 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7478 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7480 case Q3TCMOD_TRANSFORM:
7481 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
7482 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
7483 VectorSet(tcmat + 6, 0 , 0 , 1);
7484 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
7485 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7487 case Q3TCMOD_TURBULENT:
7488 // this is handled in the RSurf_PrepareVertices function
7489 matrix = identitymatrix;
7493 Matrix4x4_Concat(texmatrix, &matrix, &temp);
7496 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7498 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7499 char name[MAX_QPATH];
7500 skinframe_t *skinframe;
7501 unsigned char pixels[296*194];
7502 strlcpy(cache->name, skinname, sizeof(cache->name));
7503 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7504 if (developer_loading.integer)
7505 Con_Printf("loading %s\n", name);
7506 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7507 if (!skinframe || !skinframe->base)
7510 fs_offset_t filesize;
7512 f = FS_LoadFile(name, tempmempool, true, &filesize);
7515 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7516 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7520 cache->skinframe = skinframe;
7523 texture_t *R_GetCurrentTexture(texture_t *t)
7526 const entity_render_t *ent = rsurface.entity;
7527 dp_model_t *model = ent->model;
7528 q3shaderinfo_layer_tcmod_t *tcmod;
7530 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7531 return t->currentframe;
7532 t->update_lastrenderframe = r_textureframe;
7533 t->update_lastrenderentity = (void *)ent;
7535 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7536 t->camera_entity = ent->entitynumber;
7538 t->camera_entity = 0;
7540 // switch to an alternate material if this is a q1bsp animated material
7542 texture_t *texture = t;
7543 int s = rsurface.ent_skinnum;
7544 if ((unsigned int)s >= (unsigned int)model->numskins)
7546 if (model->skinscenes)
7548 if (model->skinscenes[s].framecount > 1)
7549 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7551 s = model->skinscenes[s].firstframe;
7554 t = t + s * model->num_surfaces;
7557 // use an alternate animation if the entity's frame is not 0,
7558 // and only if the texture has an alternate animation
7559 if (rsurface.ent_alttextures && t->anim_total[1])
7560 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
7562 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
7564 texture->currentframe = t;
7567 // update currentskinframe to be a qw skin or animation frame
7568 if (rsurface.ent_qwskin >= 0)
7570 i = rsurface.ent_qwskin;
7571 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7573 r_qwskincache_size = cl.maxclients;
7575 Mem_Free(r_qwskincache);
7576 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7578 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7579 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7580 t->currentskinframe = r_qwskincache[i].skinframe;
7581 if (t->currentskinframe == NULL)
7582 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7584 else if (t->numskinframes >= 2)
7585 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7586 if (t->backgroundnumskinframes >= 2)
7587 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
7589 t->currentmaterialflags = t->basematerialflags;
7590 t->currentalpha = rsurface.colormod[3];
7591 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
7592 t->currentalpha *= r_wateralpha.value;
7593 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7594 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7595 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7596 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7597 if (!(rsurface.ent_flags & RENDER_LIGHT))
7598 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7599 else if (FAKELIGHT_ENABLED)
7601 // no modellight if using fakelight for the map
7603 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7605 // pick a model lighting mode
7606 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7607 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7609 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7611 if (rsurface.ent_flags & RENDER_ADDITIVE)
7612 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7613 else if (t->currentalpha < 1)
7614 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7615 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7616 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7617 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7618 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7619 if (t->backgroundnumskinframes)
7620 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7621 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7623 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7624 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7627 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7628 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7629 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7631 // there is no tcmod
7632 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7634 t->currenttexmatrix = r_waterscrollmatrix;
7635 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7637 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7639 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7640 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7643 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7644 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7645 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7646 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7648 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7649 if (t->currentskinframe->qpixels)
7650 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7651 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7652 if (!t->basetexture)
7653 t->basetexture = r_texture_notexture;
7654 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7655 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7656 t->nmaptexture = t->currentskinframe->nmap;
7657 if (!t->nmaptexture)
7658 t->nmaptexture = r_texture_blanknormalmap;
7659 t->glosstexture = r_texture_black;
7660 t->glowtexture = t->currentskinframe->glow;
7661 t->fogtexture = t->currentskinframe->fog;
7662 t->reflectmasktexture = t->currentskinframe->reflect;
7663 if (t->backgroundnumskinframes)
7665 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7666 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7667 t->backgroundglosstexture = r_texture_black;
7668 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7669 if (!t->backgroundnmaptexture)
7670 t->backgroundnmaptexture = r_texture_blanknormalmap;
7674 t->backgroundbasetexture = r_texture_white;
7675 t->backgroundnmaptexture = r_texture_blanknormalmap;
7676 t->backgroundglosstexture = r_texture_black;
7677 t->backgroundglowtexture = NULL;
7679 t->specularpower = r_shadow_glossexponent.value;
7680 // TODO: store reference values for these in the texture?
7681 t->specularscale = 0;
7682 if (r_shadow_gloss.integer > 0)
7684 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7686 if (r_shadow_glossintensity.value > 0)
7688 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7689 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7690 t->specularscale = r_shadow_glossintensity.value;
7693 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7695 t->glosstexture = r_texture_white;
7696 t->backgroundglosstexture = r_texture_white;
7697 t->specularscale = r_shadow_gloss2intensity.value;
7698 t->specularpower = r_shadow_gloss2exponent.value;
7701 t->specularscale *= t->specularscalemod;
7702 t->specularpower *= t->specularpowermod;
7704 // lightmaps mode looks bad with dlights using actual texturing, so turn
7705 // off the colormap and glossmap, but leave the normalmap on as it still
7706 // accurately represents the shading involved
7707 if (gl_lightmaps.integer)
7709 t->basetexture = r_texture_grey128;
7710 t->pantstexture = r_texture_black;
7711 t->shirttexture = r_texture_black;
7712 t->nmaptexture = r_texture_blanknormalmap;
7713 t->glosstexture = r_texture_black;
7714 t->glowtexture = NULL;
7715 t->fogtexture = NULL;
7716 t->reflectmasktexture = NULL;
7717 t->backgroundbasetexture = NULL;
7718 t->backgroundnmaptexture = r_texture_blanknormalmap;
7719 t->backgroundglosstexture = r_texture_black;
7720 t->backgroundglowtexture = NULL;
7721 t->specularscale = 0;
7722 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7725 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7726 VectorClear(t->dlightcolor);
7727 t->currentnumlayers = 0;
7728 if (t->currentmaterialflags & MATERIALFLAG_WALL)
7730 int blendfunc1, blendfunc2;
7732 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7734 blendfunc1 = GL_SRC_ALPHA;
7735 blendfunc2 = GL_ONE;
7737 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7739 blendfunc1 = GL_SRC_ALPHA;
7740 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7742 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7744 blendfunc1 = t->customblendfunc[0];
7745 blendfunc2 = t->customblendfunc[1];
7749 blendfunc1 = GL_ONE;
7750 blendfunc2 = GL_ZERO;
7752 // don't colormod evilblend textures
7753 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7754 VectorSet(t->lightmapcolor, 1, 1, 1);
7755 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7756 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7758 // fullbright is not affected by r_refdef.lightmapintensity
7759 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]);
7760 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7761 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]);
7762 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7763 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]);
7767 vec3_t ambientcolor;
7769 // set the color tint used for lights affecting this surface
7770 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7772 // q3bsp has no lightmap updates, so the lightstylevalue that
7773 // would normally be baked into the lightmap must be
7774 // applied to the color
7775 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7776 if (model->type == mod_brushq3)
7777 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7778 colorscale *= r_refdef.lightmapintensity;
7779 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7780 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7781 // basic lit geometry
7782 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]);
7783 // add pants/shirt if needed
7784 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7785 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]);
7786 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7787 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]);
7788 // now add ambient passes if needed
7789 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7791 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]);
7792 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7793 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]);
7794 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7795 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]);
7798 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7799 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]);
7800 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7802 // if this is opaque use alpha blend which will darken the earlier
7805 // if this is an alpha blended material, all the earlier passes
7806 // were darkened by fog already, so we only need to add the fog
7807 // color ontop through the fog mask texture
7809 // if this is an additive blended material, all the earlier passes
7810 // were darkened by fog already, and we should not add fog color
7811 // (because the background was not darkened, there is no fog color
7812 // that was lost behind it).
7813 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]);
7817 return t->currentframe;
7820 rsurfacestate_t rsurface;
7822 void RSurf_ActiveWorldEntity(void)
7824 dp_model_t *model = r_refdef.scene.worldmodel;
7825 //if (rsurface.entity == r_refdef.scene.worldentity)
7827 rsurface.entity = r_refdef.scene.worldentity;
7828 rsurface.skeleton = NULL;
7829 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7830 rsurface.ent_skinnum = 0;
7831 rsurface.ent_qwskin = -1;
7832 rsurface.ent_shadertime = 0;
7833 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7834 rsurface.matrix = identitymatrix;
7835 rsurface.inversematrix = identitymatrix;
7836 rsurface.matrixscale = 1;
7837 rsurface.inversematrixscale = 1;
7838 R_EntityMatrix(&identitymatrix);
7839 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7840 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7841 rsurface.fograngerecip = r_refdef.fograngerecip;
7842 rsurface.fogheightfade = r_refdef.fogheightfade;
7843 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7844 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7845 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7846 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7847 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7848 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7849 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7850 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7851 rsurface.colormod[3] = 1;
7852 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);
7853 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7854 rsurface.frameblend[0].lerp = 1;
7855 rsurface.ent_alttextures = false;
7856 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7857 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7858 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7859 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7860 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7861 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7862 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7863 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7864 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7865 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7866 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7867 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7868 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7869 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7870 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7871 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7872 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7873 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7874 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7875 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7876 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7877 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7878 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7879 rsurface.modelelement3i = model->surfmesh.data_element3i;
7880 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7881 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7882 rsurface.modelelement3s = model->surfmesh.data_element3s;
7883 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7884 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7885 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7886 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7887 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7888 rsurface.modelsurfaces = model->data_surfaces;
7889 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7890 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7891 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7892 rsurface.modelgeneratedvertex = false;
7893 rsurface.batchgeneratedvertex = false;
7894 rsurface.batchfirstvertex = 0;
7895 rsurface.batchnumvertices = 0;
7896 rsurface.batchfirsttriangle = 0;
7897 rsurface.batchnumtriangles = 0;
7898 rsurface.batchvertex3f = NULL;
7899 rsurface.batchvertex3f_vertexbuffer = NULL;
7900 rsurface.batchvertex3f_bufferoffset = 0;
7901 rsurface.batchsvector3f = NULL;
7902 rsurface.batchsvector3f_vertexbuffer = NULL;
7903 rsurface.batchsvector3f_bufferoffset = 0;
7904 rsurface.batchtvector3f = NULL;
7905 rsurface.batchtvector3f_vertexbuffer = NULL;
7906 rsurface.batchtvector3f_bufferoffset = 0;
7907 rsurface.batchnormal3f = NULL;
7908 rsurface.batchnormal3f_vertexbuffer = NULL;
7909 rsurface.batchnormal3f_bufferoffset = 0;
7910 rsurface.batchlightmapcolor4f = NULL;
7911 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7912 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7913 rsurface.batchtexcoordtexture2f = NULL;
7914 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7915 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7916 rsurface.batchtexcoordlightmap2f = NULL;
7917 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7918 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7919 rsurface.batchvertexmesh = NULL;
7920 rsurface.batchvertexmeshbuffer = NULL;
7921 rsurface.batchvertex3fbuffer = NULL;
7922 rsurface.batchelement3i = NULL;
7923 rsurface.batchelement3i_indexbuffer = NULL;
7924 rsurface.batchelement3i_bufferoffset = 0;
7925 rsurface.batchelement3s = NULL;
7926 rsurface.batchelement3s_indexbuffer = NULL;
7927 rsurface.batchelement3s_bufferoffset = 0;
7928 rsurface.passcolor4f = NULL;
7929 rsurface.passcolor4f_vertexbuffer = NULL;
7930 rsurface.passcolor4f_bufferoffset = 0;
7933 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7935 dp_model_t *model = ent->model;
7936 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7938 rsurface.entity = (entity_render_t *)ent;
7939 rsurface.skeleton = ent->skeleton;
7940 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7941 rsurface.ent_skinnum = ent->skinnum;
7942 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;
7943 rsurface.ent_shadertime = ent->shadertime;
7944 rsurface.ent_flags = ent->flags;
7945 rsurface.matrix = ent->matrix;
7946 rsurface.inversematrix = ent->inversematrix;
7947 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7948 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7949 R_EntityMatrix(&rsurface.matrix);
7950 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7951 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7952 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7953 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7954 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7955 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7956 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7957 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7958 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7959 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7960 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7961 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7962 rsurface.colormod[3] = ent->alpha;
7963 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7964 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7965 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7966 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7967 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7968 if (ent->model->brush.submodel && !prepass)
7970 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7971 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7973 if (model->surfmesh.isanimated && model->AnimateVertices)
7975 if (ent->animcache_vertex3f)
7977 rsurface.modelvertex3f = ent->animcache_vertex3f;
7978 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7979 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7980 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7981 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7982 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
7983 rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
7985 else if (wanttangents)
7987 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7988 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7989 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7990 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7991 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7992 rsurface.modelvertexmesh = NULL;
7993 rsurface.modelvertexmeshbuffer = NULL;
7994 rsurface.modelvertex3fbuffer = NULL;
7996 else if (wantnormals)
7998 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7999 rsurface.modelsvector3f = NULL;
8000 rsurface.modeltvector3f = NULL;
8001 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8002 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8003 rsurface.modelvertexmesh = NULL;
8004 rsurface.modelvertexmeshbuffer = NULL;
8005 rsurface.modelvertex3fbuffer = NULL;
8009 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8010 rsurface.modelsvector3f = NULL;
8011 rsurface.modeltvector3f = NULL;
8012 rsurface.modelnormal3f = NULL;
8013 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8014 rsurface.modelvertexmesh = NULL;
8015 rsurface.modelvertexmeshbuffer = NULL;
8016 rsurface.modelvertex3fbuffer = NULL;
8018 rsurface.modelvertex3f_vertexbuffer = 0;
8019 rsurface.modelvertex3f_bufferoffset = 0;
8020 rsurface.modelsvector3f_vertexbuffer = 0;
8021 rsurface.modelsvector3f_bufferoffset = 0;
8022 rsurface.modeltvector3f_vertexbuffer = 0;
8023 rsurface.modeltvector3f_bufferoffset = 0;
8024 rsurface.modelnormal3f_vertexbuffer = 0;
8025 rsurface.modelnormal3f_bufferoffset = 0;
8026 rsurface.modelgeneratedvertex = true;
8030 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8031 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8032 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8033 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8034 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8035 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8036 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8037 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8038 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8039 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8040 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8041 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8042 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8043 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8044 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8045 rsurface.modelgeneratedvertex = false;
8047 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8048 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8049 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8050 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8051 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8052 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8053 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8054 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8055 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8056 rsurface.modelelement3i = model->surfmesh.data_element3i;
8057 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8058 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8059 rsurface.modelelement3s = model->surfmesh.data_element3s;
8060 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8061 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8062 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8063 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8064 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8065 rsurface.modelsurfaces = model->data_surfaces;
8066 rsurface.batchgeneratedvertex = false;
8067 rsurface.batchfirstvertex = 0;
8068 rsurface.batchnumvertices = 0;
8069 rsurface.batchfirsttriangle = 0;
8070 rsurface.batchnumtriangles = 0;
8071 rsurface.batchvertex3f = NULL;
8072 rsurface.batchvertex3f_vertexbuffer = NULL;
8073 rsurface.batchvertex3f_bufferoffset = 0;
8074 rsurface.batchsvector3f = NULL;
8075 rsurface.batchsvector3f_vertexbuffer = NULL;
8076 rsurface.batchsvector3f_bufferoffset = 0;
8077 rsurface.batchtvector3f = NULL;
8078 rsurface.batchtvector3f_vertexbuffer = NULL;
8079 rsurface.batchtvector3f_bufferoffset = 0;
8080 rsurface.batchnormal3f = NULL;
8081 rsurface.batchnormal3f_vertexbuffer = NULL;
8082 rsurface.batchnormal3f_bufferoffset = 0;
8083 rsurface.batchlightmapcolor4f = NULL;
8084 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8085 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8086 rsurface.batchtexcoordtexture2f = NULL;
8087 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8088 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8089 rsurface.batchtexcoordlightmap2f = NULL;
8090 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8091 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8092 rsurface.batchvertexmesh = NULL;
8093 rsurface.batchvertexmeshbuffer = NULL;
8094 rsurface.batchvertex3fbuffer = NULL;
8095 rsurface.batchelement3i = NULL;
8096 rsurface.batchelement3i_indexbuffer = NULL;
8097 rsurface.batchelement3i_bufferoffset = 0;
8098 rsurface.batchelement3s = NULL;
8099 rsurface.batchelement3s_indexbuffer = NULL;
8100 rsurface.batchelement3s_bufferoffset = 0;
8101 rsurface.passcolor4f = NULL;
8102 rsurface.passcolor4f_vertexbuffer = NULL;
8103 rsurface.passcolor4f_bufferoffset = 0;
8106 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)
8108 rsurface.entity = r_refdef.scene.worldentity;
8109 rsurface.skeleton = NULL;
8110 rsurface.ent_skinnum = 0;
8111 rsurface.ent_qwskin = -1;
8112 rsurface.ent_shadertime = shadertime;
8113 rsurface.ent_flags = entflags;
8114 rsurface.modelnumvertices = numvertices;
8115 rsurface.modelnumtriangles = numtriangles;
8116 rsurface.matrix = *matrix;
8117 rsurface.inversematrix = *inversematrix;
8118 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8119 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8120 R_EntityMatrix(&rsurface.matrix);
8121 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8122 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8123 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8124 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8125 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8126 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8127 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8128 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8129 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8130 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8131 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8132 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8133 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);
8134 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8135 rsurface.frameblend[0].lerp = 1;
8136 rsurface.ent_alttextures = false;
8137 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8138 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8141 rsurface.modelvertex3f = (float *)vertex3f;
8142 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8143 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8144 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8146 else if (wantnormals)
8148 rsurface.modelvertex3f = (float *)vertex3f;
8149 rsurface.modelsvector3f = NULL;
8150 rsurface.modeltvector3f = NULL;
8151 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8155 rsurface.modelvertex3f = (float *)vertex3f;
8156 rsurface.modelsvector3f = NULL;
8157 rsurface.modeltvector3f = NULL;
8158 rsurface.modelnormal3f = NULL;
8160 rsurface.modelvertexmesh = NULL;
8161 rsurface.modelvertexmeshbuffer = NULL;
8162 rsurface.modelvertex3fbuffer = NULL;
8163 rsurface.modelvertex3f_vertexbuffer = 0;
8164 rsurface.modelvertex3f_bufferoffset = 0;
8165 rsurface.modelsvector3f_vertexbuffer = 0;
8166 rsurface.modelsvector3f_bufferoffset = 0;
8167 rsurface.modeltvector3f_vertexbuffer = 0;
8168 rsurface.modeltvector3f_bufferoffset = 0;
8169 rsurface.modelnormal3f_vertexbuffer = 0;
8170 rsurface.modelnormal3f_bufferoffset = 0;
8171 rsurface.modelgeneratedvertex = true;
8172 rsurface.modellightmapcolor4f = (float *)color4f;
8173 rsurface.modellightmapcolor4f_vertexbuffer = 0;
8174 rsurface.modellightmapcolor4f_bufferoffset = 0;
8175 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
8176 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8177 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8178 rsurface.modeltexcoordlightmap2f = NULL;
8179 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8180 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8181 rsurface.modelelement3i = (int *)element3i;
8182 rsurface.modelelement3i_indexbuffer = NULL;
8183 rsurface.modelelement3i_bufferoffset = 0;
8184 rsurface.modelelement3s = (unsigned short *)element3s;
8185 rsurface.modelelement3s_indexbuffer = NULL;
8186 rsurface.modelelement3s_bufferoffset = 0;
8187 rsurface.modellightmapoffsets = NULL;
8188 rsurface.modelsurfaces = NULL;
8189 rsurface.batchgeneratedvertex = false;
8190 rsurface.batchfirstvertex = 0;
8191 rsurface.batchnumvertices = 0;
8192 rsurface.batchfirsttriangle = 0;
8193 rsurface.batchnumtriangles = 0;
8194 rsurface.batchvertex3f = NULL;
8195 rsurface.batchvertex3f_vertexbuffer = NULL;
8196 rsurface.batchvertex3f_bufferoffset = 0;
8197 rsurface.batchsvector3f = NULL;
8198 rsurface.batchsvector3f_vertexbuffer = NULL;
8199 rsurface.batchsvector3f_bufferoffset = 0;
8200 rsurface.batchtvector3f = NULL;
8201 rsurface.batchtvector3f_vertexbuffer = NULL;
8202 rsurface.batchtvector3f_bufferoffset = 0;
8203 rsurface.batchnormal3f = NULL;
8204 rsurface.batchnormal3f_vertexbuffer = NULL;
8205 rsurface.batchnormal3f_bufferoffset = 0;
8206 rsurface.batchlightmapcolor4f = NULL;
8207 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8208 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8209 rsurface.batchtexcoordtexture2f = NULL;
8210 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8211 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8212 rsurface.batchtexcoordlightmap2f = NULL;
8213 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8214 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8215 rsurface.batchvertexmesh = NULL;
8216 rsurface.batchvertexmeshbuffer = NULL;
8217 rsurface.batchvertex3fbuffer = NULL;
8218 rsurface.batchelement3i = NULL;
8219 rsurface.batchelement3i_indexbuffer = NULL;
8220 rsurface.batchelement3i_bufferoffset = 0;
8221 rsurface.batchelement3s = NULL;
8222 rsurface.batchelement3s_indexbuffer = NULL;
8223 rsurface.batchelement3s_bufferoffset = 0;
8224 rsurface.passcolor4f = NULL;
8225 rsurface.passcolor4f_vertexbuffer = NULL;
8226 rsurface.passcolor4f_bufferoffset = 0;
8228 if (rsurface.modelnumvertices && rsurface.modelelement3i)
8230 if ((wantnormals || wanttangents) && !normal3f)
8232 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8233 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8235 if (wanttangents && !svector3f)
8237 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8238 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8239 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8244 float RSurf_FogPoint(const float *v)
8246 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8247 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8248 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8249 float FogHeightFade = r_refdef.fogheightfade;
8251 unsigned int fogmasktableindex;
8252 if (r_refdef.fogplaneviewabove)
8253 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8255 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8256 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8257 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8260 float RSurf_FogVertex(const float *v)
8262 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8263 float FogPlaneViewDist = rsurface.fogplaneviewdist;
8264 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8265 float FogHeightFade = rsurface.fogheightfade;
8267 unsigned int fogmasktableindex;
8268 if (r_refdef.fogplaneviewabove)
8269 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8271 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8272 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8273 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8276 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8279 for (i = 0;i < numelements;i++)
8280 outelement3i[i] = inelement3i[i] + adjust;
8283 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8284 extern cvar_t gl_vbo;
8285 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8293 int surfacefirsttriangle;
8294 int surfacenumtriangles;
8295 int surfacefirstvertex;
8296 int surfaceendvertex;
8297 int surfacenumvertices;
8298 int batchnumvertices;
8299 int batchnumtriangles;
8303 qboolean dynamicvertex;
8307 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8309 q3shaderinfo_deform_t *deform;
8310 const msurface_t *surface, *firstsurface;
8311 r_vertexmesh_t *vertexmesh;
8312 if (!texturenumsurfaces)
8314 // find vertex range of this surface batch
8316 firstsurface = texturesurfacelist[0];
8317 firsttriangle = firstsurface->num_firsttriangle;
8318 batchnumvertices = 0;
8319 batchnumtriangles = 0;
8320 firstvertex = endvertex = firstsurface->num_firstvertex;
8321 for (i = 0;i < texturenumsurfaces;i++)
8323 surface = texturesurfacelist[i];
8324 if (surface != firstsurface + i)
8326 surfacefirstvertex = surface->num_firstvertex;
8327 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8328 surfacenumvertices = surface->num_vertices;
8329 surfacenumtriangles = surface->num_triangles;
8330 if (firstvertex > surfacefirstvertex)
8331 firstvertex = surfacefirstvertex;
8332 if (endvertex < surfaceendvertex)
8333 endvertex = surfaceendvertex;
8334 batchnumvertices += surfacenumvertices;
8335 batchnumtriangles += surfacenumtriangles;
8338 // we now know the vertex range used, and if there are any gaps in it
8339 rsurface.batchfirstvertex = firstvertex;
8340 rsurface.batchnumvertices = endvertex - firstvertex;
8341 rsurface.batchfirsttriangle = firsttriangle;
8342 rsurface.batchnumtriangles = batchnumtriangles;
8344 // this variable holds flags for which properties have been updated that
8345 // may require regenerating vertexmesh array...
8348 // check if any dynamic vertex processing must occur
8349 dynamicvertex = false;
8351 // if there is a chance of animated vertex colors, it's a dynamic batch
8352 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8354 dynamicvertex = true;
8355 batchneed |= BATCHNEED_NOGAPS;
8356 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8359 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8361 switch (deform->deform)
8364 case Q3DEFORM_PROJECTIONSHADOW:
8365 case Q3DEFORM_TEXT0:
8366 case Q3DEFORM_TEXT1:
8367 case Q3DEFORM_TEXT2:
8368 case Q3DEFORM_TEXT3:
8369 case Q3DEFORM_TEXT4:
8370 case Q3DEFORM_TEXT5:
8371 case Q3DEFORM_TEXT6:
8372 case Q3DEFORM_TEXT7:
8375 case Q3DEFORM_AUTOSPRITE:
8376 dynamicvertex = true;
8377 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8378 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8380 case Q3DEFORM_AUTOSPRITE2:
8381 dynamicvertex = true;
8382 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8383 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8385 case Q3DEFORM_NORMAL:
8386 dynamicvertex = true;
8387 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8388 needsupdate |= 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_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8395 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8397 case Q3DEFORM_BULGE:
8398 dynamicvertex = true;
8399 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8400 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8403 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8404 break; // if wavefunc is a nop, ignore this transform
8405 dynamicvertex = true;
8406 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8407 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8411 switch(rsurface.texture->tcgen.tcgen)
8414 case Q3TCGEN_TEXTURE:
8416 case Q3TCGEN_LIGHTMAP:
8417 dynamicvertex = true;
8418 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8419 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8421 case Q3TCGEN_VECTOR:
8422 dynamicvertex = true;
8423 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8424 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8426 case Q3TCGEN_ENVIRONMENT:
8427 dynamicvertex = true;
8428 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8429 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8432 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8434 dynamicvertex = true;
8435 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8436 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8439 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8441 dynamicvertex = true;
8442 batchneed |= BATCHNEED_NOGAPS;
8443 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8446 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8448 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8449 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
8450 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
8451 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
8452 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8453 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8454 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8457 // when the model data has no vertex buffer (dynamic mesh), we need to
8459 if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8460 batchneed |= BATCHNEED_NOGAPS;
8462 // if needsupdate, we have to do a dynamic vertex batch for sure
8463 if (needsupdate & batchneed)
8464 dynamicvertex = true;
8466 // see if we need to build vertexmesh from arrays
8467 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8468 dynamicvertex = true;
8470 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8471 // also some drivers strongly dislike firstvertex
8472 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8473 dynamicvertex = true;
8475 rsurface.batchvertex3f = rsurface.modelvertex3f;
8476 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8477 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8478 rsurface.batchsvector3f = rsurface.modelsvector3f;
8479 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8480 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8481 rsurface.batchtvector3f = rsurface.modeltvector3f;
8482 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8483 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8484 rsurface.batchnormal3f = rsurface.modelnormal3f;
8485 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8486 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8487 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8488 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
8489 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8490 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8491 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
8492 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
8493 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8494 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8495 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8496 rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8497 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8498 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8499 rsurface.batchelement3i = rsurface.modelelement3i;
8500 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8501 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8502 rsurface.batchelement3s = rsurface.modelelement3s;
8503 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8504 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8506 // if any dynamic vertex processing has to occur in software, we copy the
8507 // entire surface list together before processing to rebase the vertices
8508 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8510 // if any gaps exist and we do not have a static vertex buffer, we have to
8511 // copy the surface list together to avoid wasting upload bandwidth on the
8512 // vertices in the gaps.
8514 // if gaps exist and we have a static vertex buffer, we still have to
8515 // combine the index buffer ranges into one dynamic index buffer.
8517 // in all cases we end up with data that can be drawn in one call.
8521 // static vertex data, just set pointers...
8522 rsurface.batchgeneratedvertex = false;
8523 // if there are gaps, we want to build a combined index buffer,
8524 // otherwise use the original static buffer with an appropriate offset
8527 // build a new triangle elements array for this batch
8528 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8529 rsurface.batchfirsttriangle = 0;
8531 for (i = 0;i < texturenumsurfaces;i++)
8533 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8534 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8535 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8536 numtriangles += surfacenumtriangles;
8538 rsurface.batchelement3i_indexbuffer = NULL;
8539 rsurface.batchelement3i_bufferoffset = 0;
8540 rsurface.batchelement3s = NULL;
8541 rsurface.batchelement3s_indexbuffer = NULL;
8542 rsurface.batchelement3s_bufferoffset = 0;
8543 if (endvertex <= 65536)
8545 // make a 16bit (unsigned short) index array if possible
8546 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8547 for (i = 0;i < numtriangles*3;i++)
8548 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8554 // something needs software processing, do it for real...
8555 // we only directly handle separate array data in this case and then
8556 // generate interleaved data if needed...
8557 rsurface.batchgeneratedvertex = true;
8559 // now copy the vertex data into a combined array and make an index array
8560 // (this is what Quake3 does all the time)
8561 //if (gaps || rsurface.batchfirstvertex)
8563 rsurface.batchvertex3fbuffer = NULL;
8564 rsurface.batchvertexmesh = NULL;
8565 rsurface.batchvertexmeshbuffer = NULL;
8566 rsurface.batchvertex3f = NULL;
8567 rsurface.batchvertex3f_vertexbuffer = NULL;
8568 rsurface.batchvertex3f_bufferoffset = 0;
8569 rsurface.batchsvector3f = NULL;
8570 rsurface.batchsvector3f_vertexbuffer = NULL;
8571 rsurface.batchsvector3f_bufferoffset = 0;
8572 rsurface.batchtvector3f = NULL;
8573 rsurface.batchtvector3f_vertexbuffer = NULL;
8574 rsurface.batchtvector3f_bufferoffset = 0;
8575 rsurface.batchnormal3f = NULL;
8576 rsurface.batchnormal3f_vertexbuffer = NULL;
8577 rsurface.batchnormal3f_bufferoffset = 0;
8578 rsurface.batchlightmapcolor4f = NULL;
8579 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8580 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8581 rsurface.batchtexcoordtexture2f = NULL;
8582 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8583 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8584 rsurface.batchtexcoordlightmap2f = NULL;
8585 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8586 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8587 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8588 rsurface.batchelement3i_indexbuffer = NULL;
8589 rsurface.batchelement3i_bufferoffset = 0;
8590 rsurface.batchelement3s = NULL;
8591 rsurface.batchelement3s_indexbuffer = NULL;
8592 rsurface.batchelement3s_bufferoffset = 0;
8593 // we'll only be setting up certain arrays as needed
8594 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8595 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8596 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8597 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8598 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8599 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8600 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8602 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8603 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8605 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8606 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8607 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8608 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8609 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8610 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8613 for (i = 0;i < texturenumsurfaces;i++)
8615 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8616 surfacenumvertices = texturesurfacelist[i]->num_vertices;
8617 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8618 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8619 // copy only the data requested
8620 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8621 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8622 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8624 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8625 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8626 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
8627 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8628 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && 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]));
8633 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
8634 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8635 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
8636 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8637 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
8638 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8640 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8641 numvertices += surfacenumvertices;
8642 numtriangles += surfacenumtriangles;
8645 // generate a 16bit index array as well if possible
8646 // (in general, dynamic batches fit)
8647 if (numvertices <= 65536)
8649 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8650 for (i = 0;i < numtriangles*3;i++)
8651 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8654 // since we've copied everything, the batch now starts at 0
8655 rsurface.batchfirstvertex = 0;
8656 rsurface.batchnumvertices = batchnumvertices;
8657 rsurface.batchfirsttriangle = 0;
8658 rsurface.batchnumtriangles = batchnumtriangles;
8661 // q1bsp surfaces rendered in vertex color mode have to have colors
8662 // calculated based on lightstyles
8663 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8665 // generate color arrays for the surfaces in this list
8670 const unsigned char *lm;
8671 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8672 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8673 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8675 for (i = 0;i < texturenumsurfaces;i++)
8677 surface = texturesurfacelist[i];
8678 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8679 surfacenumvertices = surface->num_vertices;
8680 if (surface->lightmapinfo->samples)
8682 for (j = 0;j < surfacenumvertices;j++)
8684 lm = surface->lightmapinfo->samples + offsets[j];
8685 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8686 VectorScale(lm, scale, c);
8687 if (surface->lightmapinfo->styles[1] != 255)
8689 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8691 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8692 VectorMA(c, scale, lm, c);
8693 if (surface->lightmapinfo->styles[2] != 255)
8696 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8697 VectorMA(c, scale, lm, c);
8698 if (surface->lightmapinfo->styles[3] != 255)
8701 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8702 VectorMA(c, scale, lm, c);
8709 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);
8715 for (j = 0;j < surfacenumvertices;j++)
8717 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8724 // if vertices are deformed (sprite flares and things in maps, possibly
8725 // water waves, bulges and other deformations), modify the copied vertices
8727 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8729 switch (deform->deform)
8732 case Q3DEFORM_PROJECTIONSHADOW:
8733 case Q3DEFORM_TEXT0:
8734 case Q3DEFORM_TEXT1:
8735 case Q3DEFORM_TEXT2:
8736 case Q3DEFORM_TEXT3:
8737 case Q3DEFORM_TEXT4:
8738 case Q3DEFORM_TEXT5:
8739 case Q3DEFORM_TEXT6:
8740 case Q3DEFORM_TEXT7:
8743 case Q3DEFORM_AUTOSPRITE:
8744 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8745 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8746 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8747 VectorNormalize(newforward);
8748 VectorNormalize(newright);
8749 VectorNormalize(newup);
8750 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8751 // rsurface.batchvertex3f_vertexbuffer = NULL;
8752 // rsurface.batchvertex3f_bufferoffset = 0;
8753 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8754 // rsurface.batchsvector3f_vertexbuffer = NULL;
8755 // rsurface.batchsvector3f_bufferoffset = 0;
8756 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8757 // rsurface.batchtvector3f_vertexbuffer = NULL;
8758 // rsurface.batchtvector3f_bufferoffset = 0;
8759 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8760 // rsurface.batchnormal3f_vertexbuffer = NULL;
8761 // rsurface.batchnormal3f_bufferoffset = 0;
8762 // a single autosprite surface can contain multiple sprites...
8763 for (j = 0;j < batchnumvertices - 3;j += 4)
8765 VectorClear(center);
8766 for (i = 0;i < 4;i++)
8767 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8768 VectorScale(center, 0.25f, center);
8769 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8770 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8771 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8772 for (i = 0;i < 4;i++)
8774 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8775 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8778 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8779 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8780 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);
8782 case Q3DEFORM_AUTOSPRITE2:
8783 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8784 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8785 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8786 VectorNormalize(newforward);
8787 VectorNormalize(newright);
8788 VectorNormalize(newup);
8789 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8790 // rsurface.batchvertex3f_vertexbuffer = NULL;
8791 // rsurface.batchvertex3f_bufferoffset = 0;
8793 const float *v1, *v2;
8803 memset(shortest, 0, sizeof(shortest));
8804 // a single autosprite surface can contain multiple sprites...
8805 for (j = 0;j < batchnumvertices - 3;j += 4)
8807 VectorClear(center);
8808 for (i = 0;i < 4;i++)
8809 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8810 VectorScale(center, 0.25f, center);
8811 // find the two shortest edges, then use them to define the
8812 // axis vectors for rotating around the central axis
8813 for (i = 0;i < 6;i++)
8815 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8816 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8817 l = VectorDistance2(v1, v2);
8818 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8820 l += (1.0f / 1024.0f);
8821 if (shortest[0].length2 > l || i == 0)
8823 shortest[1] = shortest[0];
8824 shortest[0].length2 = l;
8825 shortest[0].v1 = v1;
8826 shortest[0].v2 = v2;
8828 else if (shortest[1].length2 > l || i == 1)
8830 shortest[1].length2 = l;
8831 shortest[1].v1 = v1;
8832 shortest[1].v2 = v2;
8835 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8836 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8837 // this calculates the right vector from the shortest edge
8838 // and the up vector from the edge midpoints
8839 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8840 VectorNormalize(right);
8841 VectorSubtract(end, start, up);
8842 VectorNormalize(up);
8843 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8844 VectorSubtract(rsurface.localvieworigin, center, forward);
8845 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8846 VectorNegate(forward, forward);
8847 VectorReflect(forward, 0, up, forward);
8848 VectorNormalize(forward);
8849 CrossProduct(up, forward, newright);
8850 VectorNormalize(newright);
8851 // rotate the quad around the up axis vector, this is made
8852 // especially easy by the fact we know the quad is flat,
8853 // so we only have to subtract the center position and
8854 // measure distance along the right vector, and then
8855 // multiply that by the newright vector and add back the
8857 // we also need to subtract the old position to undo the
8858 // displacement from the center, which we do with a
8859 // DotProduct, the subtraction/addition of center is also
8860 // optimized into DotProducts here
8861 l = DotProduct(right, center);
8862 for (i = 0;i < 4;i++)
8864 v1 = rsurface.batchvertex3f + 3*(j+i);
8865 f = DotProduct(right, v1) - l;
8866 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8870 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8872 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8873 // rsurface.batchnormal3f_vertexbuffer = NULL;
8874 // rsurface.batchnormal3f_bufferoffset = 0;
8875 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8877 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8879 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8880 // rsurface.batchsvector3f_vertexbuffer = NULL;
8881 // rsurface.batchsvector3f_bufferoffset = 0;
8882 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8883 // rsurface.batchtvector3f_vertexbuffer = NULL;
8884 // rsurface.batchtvector3f_bufferoffset = 0;
8885 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
8888 case Q3DEFORM_NORMAL:
8889 // deform the normals to make reflections wavey
8890 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8891 rsurface.batchnormal3f_vertexbuffer = NULL;
8892 rsurface.batchnormal3f_bufferoffset = 0;
8893 for (j = 0;j < batchnumvertices;j++)
8896 float *normal = rsurface.batchnormal3f + 3*j;
8897 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8898 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8899 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8900 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8901 VectorNormalize(normal);
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);
8915 // deform vertex array to make wavey water and flags and such
8916 waveparms[0] = deform->waveparms[0];
8917 waveparms[1] = deform->waveparms[1];
8918 waveparms[2] = deform->waveparms[2];
8919 waveparms[3] = deform->waveparms[3];
8920 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8921 break; // if wavefunc is a nop, don't make a dynamic vertex array
8922 // this is how a divisor of vertex influence on deformation
8923 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8924 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8925 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8926 // rsurface.batchvertex3f_vertexbuffer = NULL;
8927 // rsurface.batchvertex3f_bufferoffset = 0;
8928 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8929 // rsurface.batchnormal3f_vertexbuffer = NULL;
8930 // rsurface.batchnormal3f_bufferoffset = 0;
8931 for (j = 0;j < batchnumvertices;j++)
8933 // if the wavefunc depends on time, evaluate it per-vertex
8936 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8937 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8939 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8941 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8942 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8943 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8945 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8946 // rsurface.batchsvector3f_vertexbuffer = NULL;
8947 // rsurface.batchsvector3f_bufferoffset = 0;
8948 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8949 // rsurface.batchtvector3f_vertexbuffer = NULL;
8950 // rsurface.batchtvector3f_bufferoffset = 0;
8951 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
8954 case Q3DEFORM_BULGE:
8955 // deform vertex array to make the surface have moving bulges
8956 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8957 // rsurface.batchvertex3f_vertexbuffer = NULL;
8958 // rsurface.batchvertex3f_bufferoffset = 0;
8959 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8960 // rsurface.batchnormal3f_vertexbuffer = NULL;
8961 // rsurface.batchnormal3f_bufferoffset = 0;
8962 for (j = 0;j < batchnumvertices;j++)
8964 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
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);
8981 // deform vertex array
8982 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8983 break; // if wavefunc is a nop, don't make a dynamic vertex array
8984 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8985 VectorScale(deform->parms, scale, waveparms);
8986 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8987 // rsurface.batchvertex3f_vertexbuffer = NULL;
8988 // rsurface.batchvertex3f_bufferoffset = 0;
8989 for (j = 0;j < batchnumvertices;j++)
8990 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8995 // generate texcoords based on the chosen texcoord source
8996 switch(rsurface.texture->tcgen.tcgen)
8999 case Q3TCGEN_TEXTURE:
9001 case Q3TCGEN_LIGHTMAP:
9002 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9003 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9004 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9005 if (rsurface.batchtexcoordlightmap2f)
9006 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9008 case Q3TCGEN_VECTOR:
9009 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9010 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9011 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9012 for (j = 0;j < batchnumvertices;j++)
9014 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9015 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9018 case Q3TCGEN_ENVIRONMENT:
9019 // make environment reflections using a spheremap
9020 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9021 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9022 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9023 for (j = 0;j < batchnumvertices;j++)
9025 // identical to Q3A's method, but executed in worldspace so
9026 // carried models can be shiny too
9028 float viewer[3], d, reflected[3], worldreflected[3];
9030 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9031 // VectorNormalize(viewer);
9033 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9035 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9036 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9037 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9038 // note: this is proportinal to viewer, so we can normalize later
9040 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9041 VectorNormalize(worldreflected);
9043 // note: this sphere map only uses world x and z!
9044 // so positive and negative y will LOOK THE SAME.
9045 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9046 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9050 // the only tcmod that needs software vertex processing is turbulent, so
9051 // check for it here and apply the changes if needed
9052 // and we only support that as the first one
9053 // (handling a mixture of turbulent and other tcmods would be problematic
9054 // without punting it entirely to a software path)
9055 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9057 amplitude = rsurface.texture->tcmods[0].parms[1];
9058 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
9059 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9060 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9061 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9062 for (j = 0;j < batchnumvertices;j++)
9064 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);
9065 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9069 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9071 // convert the modified arrays to vertex structs
9072 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9073 // rsurface.batchvertexmeshbuffer = NULL;
9074 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9075 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9076 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9077 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9078 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9079 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9080 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9082 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9084 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9085 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9088 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9089 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9090 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9091 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9092 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9093 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9094 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9095 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9096 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9100 void RSurf_DrawBatch(void)
9102 // sometimes a zero triangle surface (usually a degenerate patch) makes it
9103 // through the pipeline, killing it earlier in the pipeline would have
9104 // per-surface overhead rather than per-batch overhead, so it's best to
9105 // reject it here, before it hits glDraw.
9106 if (rsurface.batchnumtriangles == 0)
9109 // batch debugging code
9110 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9116 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9117 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9120 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9122 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9124 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9125 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);
9132 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);
9135 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9137 // pick the closest matching water plane
9138 int planeindex, vertexindex, bestplaneindex = -1;
9142 r_waterstate_waterplane_t *p;
9143 qboolean prepared = false;
9145 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9147 if(p->camera_entity != rsurface.texture->camera_entity)
9152 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9154 if(rsurface.batchnumvertices == 0)
9157 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9159 Matrix4x4_Transform(&rsurface.matrix, v, vert);
9160 d += fabs(PlaneDiff(vert, &p->plane));
9162 if (bestd > d || bestplaneindex < 0)
9165 bestplaneindex = planeindex;
9168 return bestplaneindex;
9169 // NOTE: this MAY return a totally unrelated water plane; we can ignore
9170 // this situation though, as it might be better to render single larger
9171 // batches with useless stuff (backface culled for example) than to
9172 // render multiple smaller batches
9175 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9178 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9179 rsurface.passcolor4f_vertexbuffer = 0;
9180 rsurface.passcolor4f_bufferoffset = 0;
9181 for (i = 0;i < rsurface.batchnumvertices;i++)
9182 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9185 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9192 if (rsurface.passcolor4f)
9194 // generate color arrays
9195 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9196 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9197 rsurface.passcolor4f_vertexbuffer = 0;
9198 rsurface.passcolor4f_bufferoffset = 0;
9199 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)
9201 f = RSurf_FogVertex(v);
9210 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9211 rsurface.passcolor4f_vertexbuffer = 0;
9212 rsurface.passcolor4f_bufferoffset = 0;
9213 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9215 f = RSurf_FogVertex(v);
9224 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9231 if (!rsurface.passcolor4f)
9233 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9234 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9235 rsurface.passcolor4f_vertexbuffer = 0;
9236 rsurface.passcolor4f_bufferoffset = 0;
9237 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)
9239 f = RSurf_FogVertex(v);
9240 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9241 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9242 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9247 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9252 if (!rsurface.passcolor4f)
9254 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9255 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9256 rsurface.passcolor4f_vertexbuffer = 0;
9257 rsurface.passcolor4f_bufferoffset = 0;
9258 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9267 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9272 if (!rsurface.passcolor4f)
9274 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9275 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9276 rsurface.passcolor4f_vertexbuffer = 0;
9277 rsurface.passcolor4f_bufferoffset = 0;
9278 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9280 c2[0] = c[0] + r_refdef.scene.ambient;
9281 c2[1] = c[1] + r_refdef.scene.ambient;
9282 c2[2] = c[2] + r_refdef.scene.ambient;
9287 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9290 rsurface.passcolor4f = NULL;
9291 rsurface.passcolor4f_vertexbuffer = 0;
9292 rsurface.passcolor4f_bufferoffset = 0;
9293 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9294 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9295 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9296 GL_Color(r, g, b, a);
9297 R_Mesh_TexBind(0, rsurface.lightmaptexture);
9301 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9303 // TODO: optimize applyfog && applycolor case
9304 // just apply fog if necessary, and tint the fog color array if necessary
9305 rsurface.passcolor4f = NULL;
9306 rsurface.passcolor4f_vertexbuffer = 0;
9307 rsurface.passcolor4f_bufferoffset = 0;
9308 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9309 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9310 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9311 GL_Color(r, g, b, a);
9315 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9318 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9319 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9320 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9321 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9322 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9323 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9324 GL_Color(r, g, b, a);
9328 static void RSurf_DrawBatch_GL11_ClampColor(void)
9333 if (!rsurface.passcolor4f)
9335 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9337 c2[0] = bound(0.0f, c1[0], 1.0f);
9338 c2[1] = bound(0.0f, c1[1], 1.0f);
9339 c2[2] = bound(0.0f, c1[2], 1.0f);
9340 c2[3] = bound(0.0f, c1[3], 1.0f);
9344 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9354 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9355 rsurface.passcolor4f_vertexbuffer = 0;
9356 rsurface.passcolor4f_bufferoffset = 0;
9357 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)
9359 f = -DotProduct(r_refdef.view.forward, n);
9361 f = f * 0.85 + 0.15; // work around so stuff won't get black
9362 f *= r_refdef.lightmapintensity;
9363 Vector4Set(c, f, f, f, 1);
9367 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9369 RSurf_DrawBatch_GL11_ApplyFakeLight();
9370 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9371 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9372 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9373 GL_Color(r, g, b, a);
9377 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9385 vec3_t ambientcolor;
9386 vec3_t diffusecolor;
9390 VectorCopy(rsurface.modellight_lightdir, lightdir);
9391 f = 0.5f * r_refdef.lightmapintensity;
9392 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9393 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9394 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9395 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9396 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9397 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9399 if (VectorLength2(diffusecolor) > 0)
9401 // q3-style directional shading
9402 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9403 rsurface.passcolor4f_vertexbuffer = 0;
9404 rsurface.passcolor4f_bufferoffset = 0;
9405 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)
9407 if ((f = DotProduct(n, lightdir)) > 0)
9408 VectorMA(ambientcolor, f, diffusecolor, c);
9410 VectorCopy(ambientcolor, c);
9417 *applycolor = false;
9421 *r = ambientcolor[0];
9422 *g = ambientcolor[1];
9423 *b = ambientcolor[2];
9424 rsurface.passcolor4f = NULL;
9425 rsurface.passcolor4f_vertexbuffer = 0;
9426 rsurface.passcolor4f_bufferoffset = 0;
9430 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9432 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9433 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9434 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9435 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9436 GL_Color(r, g, b, a);
9440 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9448 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9449 rsurface.passcolor4f_vertexbuffer = 0;
9450 rsurface.passcolor4f_bufferoffset = 0;
9452 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9454 f = 1 - RSurf_FogVertex(v);
9462 void RSurf_SetupDepthAndCulling(void)
9464 // submodels are biased to avoid z-fighting with world surfaces that they
9465 // may be exactly overlapping (avoids z-fighting artifacts on certain
9466 // doors and things in Quake maps)
9467 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9468 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9469 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9470 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9473 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9475 // transparent sky would be ridiculous
9476 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9478 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9479 skyrenderlater = true;
9480 RSurf_SetupDepthAndCulling();
9482 // LordHavoc: HalfLife maps have freaky skypolys so don't use
9483 // skymasking on them, and Quake3 never did sky masking (unlike
9484 // software Quake and software Quake2), so disable the sky masking
9485 // in Quake3 maps as it causes problems with q3map2 sky tricks,
9486 // and skymasking also looks very bad when noclipping outside the
9487 // level, so don't use it then either.
9488 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9490 R_Mesh_ResetTextureState();
9491 if (skyrendermasked)
9493 R_SetupShader_DepthOrShadow();
9494 // depth-only (masking)
9495 GL_ColorMask(0,0,0,0);
9496 // just to make sure that braindead drivers don't draw
9497 // anything despite that colormask...
9498 GL_BlendFunc(GL_ZERO, GL_ONE);
9499 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9500 if (rsurface.batchvertex3fbuffer)
9501 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9503 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9507 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9509 GL_BlendFunc(GL_ONE, GL_ZERO);
9510 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9511 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9512 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9515 if (skyrendermasked)
9516 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9518 R_Mesh_ResetTextureState();
9519 GL_Color(1, 1, 1, 1);
9522 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9523 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9524 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9526 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9530 // render screenspace normalmap to texture
9532 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9536 // bind lightmap texture
9538 // water/refraction/reflection/camera surfaces have to be handled specially
9539 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9541 int start, end, startplaneindex;
9542 for (start = 0;start < texturenumsurfaces;start = end)
9544 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9545 if(startplaneindex < 0)
9547 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9548 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9552 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9554 // now that we have a batch using the same planeindex, render it
9555 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9557 // render water or distortion background
9559 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));
9561 // blend surface on top
9562 GL_DepthMask(false);
9563 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9566 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9568 // render surface with reflection texture as input
9569 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9570 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));
9577 // render surface batch normally
9578 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9579 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
9580 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9583 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9584 GL_AlphaTest(false);
9587 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9589 // OpenGL 1.3 path - anything not completely ancient
9590 qboolean applycolor;
9593 const texturelayer_t *layer;
9594 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);
9595 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9597 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9600 int layertexrgbscale;
9601 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9603 if (layerindex == 0)
9607 GL_AlphaTest(false);
9608 GL_DepthFunc(GL_EQUAL);
9611 GL_DepthMask(layer->depthmask && writedepth);
9612 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9613 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9615 layertexrgbscale = 4;
9616 VectorScale(layer->color, 0.25f, layercolor);
9618 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9620 layertexrgbscale = 2;
9621 VectorScale(layer->color, 0.5f, layercolor);
9625 layertexrgbscale = 1;
9626 VectorScale(layer->color, 1.0f, layercolor);
9628 layercolor[3] = layer->color[3];
9629 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9630 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9631 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9632 switch (layer->type)
9634 case TEXTURELAYERTYPE_LITTEXTURE:
9635 // single-pass lightmapped texture with 2x rgbscale
9636 R_Mesh_TexBind(0, r_texture_white);
9637 R_Mesh_TexMatrix(0, NULL);
9638 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9639 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9640 R_Mesh_TexBind(1, layer->texture);
9641 R_Mesh_TexMatrix(1, &layer->texmatrix);
9642 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9643 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9644 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9645 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9646 else if (FAKELIGHT_ENABLED)
9647 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9648 else if (rsurface.uselightmaptexture)
9649 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9651 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9653 case TEXTURELAYERTYPE_TEXTURE:
9654 // singletexture unlit texture with transparency support
9655 R_Mesh_TexBind(0, layer->texture);
9656 R_Mesh_TexMatrix(0, &layer->texmatrix);
9657 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9658 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9659 R_Mesh_TexBind(1, 0);
9660 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9661 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9663 case TEXTURELAYERTYPE_FOG:
9664 // singletexture fogging
9667 R_Mesh_TexBind(0, layer->texture);
9668 R_Mesh_TexMatrix(0, &layer->texmatrix);
9669 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9670 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9674 R_Mesh_TexBind(0, 0);
9675 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9677 R_Mesh_TexBind(1, 0);
9678 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9679 // generate a color array for the fog pass
9680 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9681 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9685 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9688 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9690 GL_DepthFunc(GL_LEQUAL);
9691 GL_AlphaTest(false);
9695 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9697 // OpenGL 1.1 - crusty old voodoo path
9700 const texturelayer_t *layer;
9701 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);
9702 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9704 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9706 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9708 if (layerindex == 0)
9712 GL_AlphaTest(false);
9713 GL_DepthFunc(GL_EQUAL);
9716 GL_DepthMask(layer->depthmask && writedepth);
9717 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9718 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9719 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9720 switch (layer->type)
9722 case TEXTURELAYERTYPE_LITTEXTURE:
9723 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9725 // two-pass lit texture with 2x rgbscale
9726 // first the lightmap pass
9727 R_Mesh_TexBind(0, r_texture_white);
9728 R_Mesh_TexMatrix(0, NULL);
9729 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9730 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9731 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9732 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9733 else if (FAKELIGHT_ENABLED)
9734 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9735 else if (rsurface.uselightmaptexture)
9736 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9738 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9739 // then apply the texture to it
9740 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9741 R_Mesh_TexBind(0, layer->texture);
9742 R_Mesh_TexMatrix(0, &layer->texmatrix);
9743 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9744 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9745 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);
9749 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9750 R_Mesh_TexBind(0, layer->texture);
9751 R_Mesh_TexMatrix(0, &layer->texmatrix);
9752 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9753 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9754 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9755 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);
9757 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);
9760 case TEXTURELAYERTYPE_TEXTURE:
9761 // singletexture unlit texture with transparency support
9762 R_Mesh_TexBind(0, layer->texture);
9763 R_Mesh_TexMatrix(0, &layer->texmatrix);
9764 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9765 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9766 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);
9768 case TEXTURELAYERTYPE_FOG:
9769 // singletexture fogging
9772 R_Mesh_TexBind(0, layer->texture);
9773 R_Mesh_TexMatrix(0, &layer->texmatrix);
9774 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9775 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9779 R_Mesh_TexBind(0, 0);
9780 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9782 // generate a color array for the fog pass
9783 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9784 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9788 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9791 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9793 GL_DepthFunc(GL_LEQUAL);
9794 GL_AlphaTest(false);
9798 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9802 r_vertexgeneric_t *batchvertex;
9805 // R_Mesh_ResetTextureState();
9806 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9808 if(rsurface.texture && rsurface.texture->currentskinframe)
9810 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9811 c[3] *= rsurface.texture->currentalpha;
9821 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9823 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9824 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9825 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9828 // brighten it up (as texture value 127 means "unlit")
9829 c[0] *= 2 * r_refdef.view.colorscale;
9830 c[1] *= 2 * r_refdef.view.colorscale;
9831 c[2] *= 2 * r_refdef.view.colorscale;
9833 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9834 c[3] *= r_wateralpha.value;
9836 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9838 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9839 GL_DepthMask(false);
9841 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9843 GL_BlendFunc(GL_ONE, GL_ONE);
9844 GL_DepthMask(false);
9846 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9848 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9849 GL_DepthMask(false);
9851 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9853 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9854 GL_DepthMask(false);
9858 GL_BlendFunc(GL_ONE, GL_ZERO);
9859 GL_DepthMask(writedepth);
9862 if (r_showsurfaces.integer == 3)
9864 rsurface.passcolor4f = NULL;
9866 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9868 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9870 rsurface.passcolor4f = NULL;
9871 rsurface.passcolor4f_vertexbuffer = 0;
9872 rsurface.passcolor4f_bufferoffset = 0;
9874 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9876 qboolean applycolor = true;
9879 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9881 r_refdef.lightmapintensity = 1;
9882 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9883 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9885 else if (FAKELIGHT_ENABLED)
9887 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9889 r_refdef.lightmapintensity = r_fakelight_intensity.value;
9890 RSurf_DrawBatch_GL11_ApplyFakeLight();
9891 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9895 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9897 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9898 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9899 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9902 if(!rsurface.passcolor4f)
9903 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9905 RSurf_DrawBatch_GL11_ApplyAmbient();
9906 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9907 if(r_refdef.fogenabled)
9908 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9909 RSurf_DrawBatch_GL11_ClampColor();
9911 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9912 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9915 else if (!r_refdef.view.showdebug)
9917 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9918 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9919 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9921 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9922 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9924 R_Mesh_PrepareVertices_Generic_Unlock();
9927 else if (r_showsurfaces.integer == 4)
9929 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9930 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9931 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9933 unsigned char c = (vi << 3) * (1.0f / 256.0f);
9934 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9935 Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9937 R_Mesh_PrepareVertices_Generic_Unlock();
9940 else if (r_showsurfaces.integer == 2)
9943 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9944 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9945 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9947 unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9948 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9949 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9950 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9951 Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9952 Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9953 Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9955 R_Mesh_PrepareVertices_Generic_Unlock();
9956 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9960 int texturesurfaceindex;
9962 const msurface_t *surface;
9963 float surfacecolor4f[4];
9964 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9965 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9967 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9969 surface = texturesurfacelist[texturesurfaceindex];
9970 k = (int)(((size_t)surface) / sizeof(msurface_t));
9971 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9972 for (j = 0;j < surface->num_vertices;j++)
9974 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9975 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
9979 R_Mesh_PrepareVertices_Generic_Unlock();
9984 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9987 RSurf_SetupDepthAndCulling();
9988 if (r_showsurfaces.integer)
9990 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9993 switch (vid.renderpath)
9995 case RENDERPATH_GL20:
9996 case RENDERPATH_D3D9:
9997 case RENDERPATH_D3D10:
9998 case RENDERPATH_D3D11:
9999 case RENDERPATH_SOFT:
10000 case RENDERPATH_GLES2:
10001 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10003 case RENDERPATH_GL13:
10004 case RENDERPATH_GLES1:
10005 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10007 case RENDERPATH_GL11:
10008 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10014 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10017 RSurf_SetupDepthAndCulling();
10018 if (r_showsurfaces.integer)
10020 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10023 switch (vid.renderpath)
10025 case RENDERPATH_GL20:
10026 case RENDERPATH_D3D9:
10027 case RENDERPATH_D3D10:
10028 case RENDERPATH_D3D11:
10029 case RENDERPATH_SOFT:
10030 case RENDERPATH_GLES2:
10031 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10033 case RENDERPATH_GL13:
10034 case RENDERPATH_GLES1:
10035 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10037 case RENDERPATH_GL11:
10038 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10044 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10047 int texturenumsurfaces, endsurface;
10048 texture_t *texture;
10049 const msurface_t *surface;
10050 const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10052 // if the model is static it doesn't matter what value we give for
10053 // wantnormals and wanttangents, so this logic uses only rules applicable
10054 // to a model, knowing that they are meaningless otherwise
10055 if (ent == r_refdef.scene.worldentity)
10056 RSurf_ActiveWorldEntity();
10057 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10058 RSurf_ActiveModelEntity(ent, false, false, false);
10061 switch (vid.renderpath)
10063 case RENDERPATH_GL20:
10064 case RENDERPATH_D3D9:
10065 case RENDERPATH_D3D10:
10066 case RENDERPATH_D3D11:
10067 case RENDERPATH_SOFT:
10068 case RENDERPATH_GLES2:
10069 RSurf_ActiveModelEntity(ent, true, true, false);
10071 case RENDERPATH_GL11:
10072 case RENDERPATH_GL13:
10073 case RENDERPATH_GLES1:
10074 RSurf_ActiveModelEntity(ent, true, false, false);
10079 if (r_transparentdepthmasking.integer)
10081 qboolean setup = false;
10082 for (i = 0;i < numsurfaces;i = j)
10085 surface = rsurface.modelsurfaces + surfacelist[i];
10086 texture = surface->texture;
10087 rsurface.texture = R_GetCurrentTexture(texture);
10088 rsurface.lightmaptexture = NULL;
10089 rsurface.deluxemaptexture = NULL;
10090 rsurface.uselightmaptexture = false;
10091 // scan ahead until we find a different texture
10092 endsurface = min(i + 1024, numsurfaces);
10093 texturenumsurfaces = 0;
10094 texturesurfacelist[texturenumsurfaces++] = surface;
10095 for (;j < endsurface;j++)
10097 surface = rsurface.modelsurfaces + surfacelist[j];
10098 if (texture != surface->texture)
10100 texturesurfacelist[texturenumsurfaces++] = surface;
10102 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10104 // render the range of surfaces as depth
10108 GL_ColorMask(0,0,0,0);
10110 GL_DepthTest(true);
10111 GL_BlendFunc(GL_ONE, GL_ZERO);
10112 GL_DepthMask(true);
10113 // R_Mesh_ResetTextureState();
10114 R_SetupShader_DepthOrShadow();
10116 RSurf_SetupDepthAndCulling();
10117 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10118 if (rsurface.batchvertex3fbuffer)
10119 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10121 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10125 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10128 for (i = 0;i < numsurfaces;i = j)
10131 surface = rsurface.modelsurfaces + surfacelist[i];
10132 texture = surface->texture;
10133 rsurface.texture = R_GetCurrentTexture(texture);
10134 // scan ahead until we find a different texture
10135 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10136 texturenumsurfaces = 0;
10137 texturesurfacelist[texturenumsurfaces++] = surface;
10138 if(FAKELIGHT_ENABLED)
10140 rsurface.lightmaptexture = NULL;
10141 rsurface.deluxemaptexture = NULL;
10142 rsurface.uselightmaptexture = false;
10143 for (;j < endsurface;j++)
10145 surface = rsurface.modelsurfaces + surfacelist[j];
10146 if (texture != surface->texture)
10148 texturesurfacelist[texturenumsurfaces++] = surface;
10153 rsurface.lightmaptexture = surface->lightmaptexture;
10154 rsurface.deluxemaptexture = surface->deluxemaptexture;
10155 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10156 for (;j < endsurface;j++)
10158 surface = rsurface.modelsurfaces + surfacelist[j];
10159 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10161 texturesurfacelist[texturenumsurfaces++] = surface;
10164 // render the range of surfaces
10165 if (ent == r_refdef.scene.worldentity)
10166 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10168 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10170 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10173 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10175 // transparent surfaces get pushed off into the transparent queue
10176 int surfacelistindex;
10177 const msurface_t *surface;
10178 vec3_t tempcenter, center;
10179 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10181 surface = texturesurfacelist[surfacelistindex];
10182 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10183 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10184 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10185 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10186 if (queueentity->transparent_offset) // transparent offset
10188 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10189 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10190 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10192 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10196 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10198 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10200 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10202 RSurf_SetupDepthAndCulling();
10203 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10204 if (rsurface.batchvertex3fbuffer)
10205 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10207 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10211 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10213 const entity_render_t *queueentity = r_refdef.scene.worldentity;
10216 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10219 if (!rsurface.texture->currentnumlayers)
10221 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10222 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10224 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10226 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10227 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10228 else if (!rsurface.texture->currentnumlayers)
10230 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10232 // in the deferred case, transparent surfaces were queued during prepass
10233 if (!r_shadow_usingdeferredprepass)
10234 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10238 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10239 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10244 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10247 texture_t *texture;
10248 R_FrameData_SetMark();
10249 // break the surface list down into batches by texture and use of lightmapping
10250 for (i = 0;i < numsurfaces;i = j)
10253 // texture is the base texture pointer, rsurface.texture is the
10254 // current frame/skin the texture is directing us to use (for example
10255 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10256 // use skin 1 instead)
10257 texture = surfacelist[i]->texture;
10258 rsurface.texture = R_GetCurrentTexture(texture);
10259 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10261 // if this texture is not the kind we want, skip ahead to the next one
10262 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10266 if(FAKELIGHT_ENABLED || depthonly || prepass)
10268 rsurface.lightmaptexture = NULL;
10269 rsurface.deluxemaptexture = NULL;
10270 rsurface.uselightmaptexture = false;
10271 // simply scan ahead until we find a different texture or lightmap state
10272 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10277 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10278 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10279 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10280 // simply scan ahead until we find a different texture or lightmap state
10281 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10284 // render the range of surfaces
10285 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10287 R_FrameData_ReturnToMark();
10290 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10294 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10297 if (!rsurface.texture->currentnumlayers)
10299 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10300 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10302 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10304 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10305 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10306 else if (!rsurface.texture->currentnumlayers)
10308 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10310 // in the deferred case, transparent surfaces were queued during prepass
10311 if (!r_shadow_usingdeferredprepass)
10312 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10316 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10317 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10322 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10325 texture_t *texture;
10326 R_FrameData_SetMark();
10327 // break the surface list down into batches by texture and use of lightmapping
10328 for (i = 0;i < numsurfaces;i = j)
10331 // texture is the base texture pointer, rsurface.texture is the
10332 // current frame/skin the texture is directing us to use (for example
10333 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10334 // use skin 1 instead)
10335 texture = surfacelist[i]->texture;
10336 rsurface.texture = R_GetCurrentTexture(texture);
10337 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10339 // if this texture is not the kind we want, skip ahead to the next one
10340 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10344 if(FAKELIGHT_ENABLED || depthonly || prepass)
10346 rsurface.lightmaptexture = NULL;
10347 rsurface.deluxemaptexture = NULL;
10348 rsurface.uselightmaptexture = false;
10349 // simply scan ahead until we find a different texture or lightmap state
10350 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10355 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10356 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10357 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10358 // simply scan ahead until we find a different texture or lightmap state
10359 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10362 // render the range of surfaces
10363 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10365 R_FrameData_ReturnToMark();
10368 float locboxvertex3f[6*4*3] =
10370 1,0,1, 1,0,0, 1,1,0, 1,1,1,
10371 0,1,1, 0,1,0, 0,0,0, 0,0,1,
10372 1,1,1, 1,1,0, 0,1,0, 0,1,1,
10373 0,0,1, 0,0,0, 1,0,0, 1,0,1,
10374 0,0,1, 1,0,1, 1,1,1, 0,1,1,
10375 1,0,0, 0,0,0, 0,1,0, 1,1,0
10378 unsigned short locboxelements[6*2*3] =
10383 12,13,14, 12,14,15,
10384 16,17,18, 16,18,19,
10388 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10391 cl_locnode_t *loc = (cl_locnode_t *)ent;
10393 float vertex3f[6*4*3];
10395 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10396 GL_DepthMask(false);
10397 GL_DepthRange(0, 1);
10398 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10399 GL_DepthTest(true);
10400 GL_CullFace(GL_NONE);
10401 R_EntityMatrix(&identitymatrix);
10403 // R_Mesh_ResetTextureState();
10405 i = surfacelist[0];
10406 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10407 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10408 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10409 surfacelist[0] < 0 ? 0.5f : 0.125f);
10411 if (VectorCompare(loc->mins, loc->maxs))
10413 VectorSet(size, 2, 2, 2);
10414 VectorMA(loc->mins, -0.5f, size, mins);
10418 VectorCopy(loc->mins, mins);
10419 VectorSubtract(loc->maxs, loc->mins, size);
10422 for (i = 0;i < 6*4*3;)
10423 for (j = 0;j < 3;j++, i++)
10424 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10426 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10427 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10428 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10431 void R_DrawLocs(void)
10434 cl_locnode_t *loc, *nearestloc;
10436 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10437 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10439 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10440 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10444 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10446 if (decalsystem->decals)
10447 Mem_Free(decalsystem->decals);
10448 memset(decalsystem, 0, sizeof(*decalsystem));
10451 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)
10454 tridecal_t *decals;
10457 // expand or initialize the system
10458 if (decalsystem->maxdecals <= decalsystem->numdecals)
10460 decalsystem_t old = *decalsystem;
10461 qboolean useshortelements;
10462 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10463 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10464 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)));
10465 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10466 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10467 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10468 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10469 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10470 if (decalsystem->numdecals)
10471 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10473 Mem_Free(old.decals);
10474 for (i = 0;i < decalsystem->maxdecals*3;i++)
10475 decalsystem->element3i[i] = i;
10476 if (useshortelements)
10477 for (i = 0;i < decalsystem->maxdecals*3;i++)
10478 decalsystem->element3s[i] = i;
10481 // grab a decal and search for another free slot for the next one
10482 decals = decalsystem->decals;
10483 decal = decalsystem->decals + (i = decalsystem->freedecal++);
10484 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10486 decalsystem->freedecal = i;
10487 if (decalsystem->numdecals <= i)
10488 decalsystem->numdecals = i + 1;
10490 // initialize the decal
10492 decal->triangleindex = triangleindex;
10493 decal->surfaceindex = surfaceindex;
10494 decal->decalsequence = decalsequence;
10495 decal->color4f[0][0] = c0[0];
10496 decal->color4f[0][1] = c0[1];
10497 decal->color4f[0][2] = c0[2];
10498 decal->color4f[0][3] = 1;
10499 decal->color4f[1][0] = c1[0];
10500 decal->color4f[1][1] = c1[1];
10501 decal->color4f[1][2] = c1[2];
10502 decal->color4f[1][3] = 1;
10503 decal->color4f[2][0] = c2[0];
10504 decal->color4f[2][1] = c2[1];
10505 decal->color4f[2][2] = c2[2];
10506 decal->color4f[2][3] = 1;
10507 decal->vertex3f[0][0] = v0[0];
10508 decal->vertex3f[0][1] = v0[1];
10509 decal->vertex3f[0][2] = v0[2];
10510 decal->vertex3f[1][0] = v1[0];
10511 decal->vertex3f[1][1] = v1[1];
10512 decal->vertex3f[1][2] = v1[2];
10513 decal->vertex3f[2][0] = v2[0];
10514 decal->vertex3f[2][1] = v2[1];
10515 decal->vertex3f[2][2] = v2[2];
10516 decal->texcoord2f[0][0] = t0[0];
10517 decal->texcoord2f[0][1] = t0[1];
10518 decal->texcoord2f[1][0] = t1[0];
10519 decal->texcoord2f[1][1] = t1[1];
10520 decal->texcoord2f[2][0] = t2[0];
10521 decal->texcoord2f[2][1] = t2[1];
10522 TriangleNormal(v0, v1, v2, decal->plane);
10523 VectorNormalize(decal->plane);
10524 decal->plane[3] = DotProduct(v0, decal->plane);
10527 extern cvar_t cl_decals_bias;
10528 extern cvar_t cl_decals_models;
10529 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10530 // baseparms, parms, temps
10531 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)
10536 const float *vertex3f;
10537 const float *normal3f;
10539 float points[2][9][3];
10546 e = rsurface.modelelement3i + 3*triangleindex;
10548 vertex3f = rsurface.modelvertex3f;
10549 normal3f = rsurface.modelnormal3f;
10553 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10555 index = 3*e[cornerindex];
10556 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10561 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10563 index = 3*e[cornerindex];
10564 VectorCopy(vertex3f + index, v[cornerindex]);
10569 //TriangleNormal(v[0], v[1], v[2], normal);
10570 //if (DotProduct(normal, localnormal) < 0.0f)
10572 // clip by each of the box planes formed from the projection matrix
10573 // if anything survives, we emit the decal
10574 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]);
10577 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]);
10580 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]);
10583 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]);
10586 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]);
10589 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]);
10592 // some part of the triangle survived, so we have to accept it...
10595 // dynamic always uses the original triangle
10597 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10599 index = 3*e[cornerindex];
10600 VectorCopy(vertex3f + index, v[cornerindex]);
10603 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10605 // convert vertex positions to texcoords
10606 Matrix4x4_Transform(projection, v[cornerindex], temp);
10607 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10608 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10609 // calculate distance fade from the projection origin
10610 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10611 f = bound(0.0f, f, 1.0f);
10612 c[cornerindex][0] = r * f;
10613 c[cornerindex][1] = g * f;
10614 c[cornerindex][2] = b * f;
10615 c[cornerindex][3] = 1.0f;
10616 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10619 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);
10621 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10622 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);
10624 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)
10626 matrix4x4_t projection;
10627 decalsystem_t *decalsystem;
10630 const msurface_t *surface;
10631 const msurface_t *surfaces;
10632 const int *surfacelist;
10633 const texture_t *texture;
10635 int numsurfacelist;
10636 int surfacelistindex;
10639 float localorigin[3];
10640 float localnormal[3];
10641 float localmins[3];
10642 float localmaxs[3];
10645 float planes[6][4];
10648 int bih_triangles_count;
10649 int bih_triangles[256];
10650 int bih_surfaces[256];
10652 decalsystem = &ent->decalsystem;
10653 model = ent->model;
10654 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10656 R_DecalSystem_Reset(&ent->decalsystem);
10660 if (!model->brush.data_leafs && !cl_decals_models.integer)
10662 if (decalsystem->model)
10663 R_DecalSystem_Reset(decalsystem);
10667 if (decalsystem->model != model)
10668 R_DecalSystem_Reset(decalsystem);
10669 decalsystem->model = model;
10671 RSurf_ActiveModelEntity(ent, true, false, false);
10673 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10674 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10675 VectorNormalize(localnormal);
10676 localsize = worldsize*rsurface.inversematrixscale;
10677 localmins[0] = localorigin[0] - localsize;
10678 localmins[1] = localorigin[1] - localsize;
10679 localmins[2] = localorigin[2] - localsize;
10680 localmaxs[0] = localorigin[0] + localsize;
10681 localmaxs[1] = localorigin[1] + localsize;
10682 localmaxs[2] = localorigin[2] + localsize;
10684 //VectorCopy(localnormal, planes[4]);
10685 //VectorVectors(planes[4], planes[2], planes[0]);
10686 AnglesFromVectors(angles, localnormal, NULL, false);
10687 AngleVectors(angles, planes[0], planes[2], planes[4]);
10688 VectorNegate(planes[0], planes[1]);
10689 VectorNegate(planes[2], planes[3]);
10690 VectorNegate(planes[4], planes[5]);
10691 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10692 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10693 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10694 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10695 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10696 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10701 matrix4x4_t forwardprojection;
10702 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10703 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10708 float projectionvector[4][3];
10709 VectorScale(planes[0], ilocalsize, projectionvector[0]);
10710 VectorScale(planes[2], ilocalsize, projectionvector[1]);
10711 VectorScale(planes[4], ilocalsize, projectionvector[2]);
10712 projectionvector[0][0] = planes[0][0] * ilocalsize;
10713 projectionvector[0][1] = planes[1][0] * ilocalsize;
10714 projectionvector[0][2] = planes[2][0] * ilocalsize;
10715 projectionvector[1][0] = planes[0][1] * ilocalsize;
10716 projectionvector[1][1] = planes[1][1] * ilocalsize;
10717 projectionvector[1][2] = planes[2][1] * ilocalsize;
10718 projectionvector[2][0] = planes[0][2] * ilocalsize;
10719 projectionvector[2][1] = planes[1][2] * ilocalsize;
10720 projectionvector[2][2] = planes[2][2] * ilocalsize;
10721 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10722 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10723 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10724 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10728 dynamic = model->surfmesh.isanimated;
10729 numsurfacelist = model->nummodelsurfaces;
10730 surfacelist = model->sortedmodelsurfaces;
10731 surfaces = model->data_surfaces;
10734 bih_triangles_count = -1;
10737 if(model->render_bih.numleafs)
10738 bih = &model->render_bih;
10739 else if(model->collision_bih.numleafs)
10740 bih = &model->collision_bih;
10743 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10744 if(bih_triangles_count == 0)
10746 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10748 if(bih_triangles_count > 0)
10750 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10752 surfaceindex = bih_surfaces[triangleindex];
10753 surface = surfaces + surfaceindex;
10754 texture = surface->texture;
10755 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10757 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10759 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10764 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10766 surfaceindex = surfacelist[surfacelistindex];
10767 surface = surfaces + surfaceindex;
10768 // check cull box first because it rejects more than any other check
10769 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10771 // skip transparent surfaces
10772 texture = surface->texture;
10773 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10775 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10777 numtriangles = surface->num_triangles;
10778 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10779 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10784 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10785 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)
10787 int renderentityindex;
10788 float worldmins[3];
10789 float worldmaxs[3];
10790 entity_render_t *ent;
10792 if (!cl_decals_newsystem.integer)
10795 worldmins[0] = worldorigin[0] - worldsize;
10796 worldmins[1] = worldorigin[1] - worldsize;
10797 worldmins[2] = worldorigin[2] - worldsize;
10798 worldmaxs[0] = worldorigin[0] + worldsize;
10799 worldmaxs[1] = worldorigin[1] + worldsize;
10800 worldmaxs[2] = worldorigin[2] + worldsize;
10802 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10804 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10806 ent = r_refdef.scene.entities[renderentityindex];
10807 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10810 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10814 typedef struct r_decalsystem_splatqueue_s
10816 vec3_t worldorigin;
10817 vec3_t worldnormal;
10823 r_decalsystem_splatqueue_t;
10825 int r_decalsystem_numqueued = 0;
10826 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10828 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)
10830 r_decalsystem_splatqueue_t *queue;
10832 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10835 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10836 VectorCopy(worldorigin, queue->worldorigin);
10837 VectorCopy(worldnormal, queue->worldnormal);
10838 Vector4Set(queue->color, r, g, b, a);
10839 Vector4Set(queue->tcrange, s1, t1, s2, t2);
10840 queue->worldsize = worldsize;
10841 queue->decalsequence = cl.decalsequence++;
10844 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10847 r_decalsystem_splatqueue_t *queue;
10849 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10850 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);
10851 r_decalsystem_numqueued = 0;
10854 extern cvar_t cl_decals_max;
10855 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10858 decalsystem_t *decalsystem = &ent->decalsystem;
10865 if (!decalsystem->numdecals)
10868 if (r_showsurfaces.integer)
10871 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10873 R_DecalSystem_Reset(decalsystem);
10877 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10878 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10880 if (decalsystem->lastupdatetime)
10881 frametime = (cl.time - decalsystem->lastupdatetime);
10884 decalsystem->lastupdatetime = cl.time;
10885 decal = decalsystem->decals;
10886 numdecals = decalsystem->numdecals;
10888 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10890 if (decal->color4f[0][3])
10892 decal->lived += frametime;
10893 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10895 memset(decal, 0, sizeof(*decal));
10896 if (decalsystem->freedecal > i)
10897 decalsystem->freedecal = i;
10901 decal = decalsystem->decals;
10902 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10905 // collapse the array by shuffling the tail decals into the gaps
10908 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10909 decalsystem->freedecal++;
10910 if (decalsystem->freedecal == numdecals)
10912 decal[decalsystem->freedecal] = decal[--numdecals];
10915 decalsystem->numdecals = numdecals;
10917 if (numdecals <= 0)
10919 // if there are no decals left, reset decalsystem
10920 R_DecalSystem_Reset(decalsystem);
10924 extern skinframe_t *decalskinframe;
10925 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10928 decalsystem_t *decalsystem = &ent->decalsystem;
10937 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10940 numdecals = decalsystem->numdecals;
10944 if (r_showsurfaces.integer)
10947 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10949 R_DecalSystem_Reset(decalsystem);
10953 // if the model is static it doesn't matter what value we give for
10954 // wantnormals and wanttangents, so this logic uses only rules applicable
10955 // to a model, knowing that they are meaningless otherwise
10956 if (ent == r_refdef.scene.worldentity)
10957 RSurf_ActiveWorldEntity();
10959 RSurf_ActiveModelEntity(ent, false, false, false);
10961 decalsystem->lastupdatetime = cl.time;
10962 decal = decalsystem->decals;
10964 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10966 // update vertex positions for animated models
10967 v3f = decalsystem->vertex3f;
10968 c4f = decalsystem->color4f;
10969 t2f = decalsystem->texcoord2f;
10970 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10972 if (!decal->color4f[0][3])
10975 if (surfacevisible && !surfacevisible[decal->surfaceindex])
10979 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
10982 // update color values for fading decals
10983 if (decal->lived >= cl_decals_time.value)
10984 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
10988 c4f[ 0] = decal->color4f[0][0] * alpha;
10989 c4f[ 1] = decal->color4f[0][1] * alpha;
10990 c4f[ 2] = decal->color4f[0][2] * alpha;
10992 c4f[ 4] = decal->color4f[1][0] * alpha;
10993 c4f[ 5] = decal->color4f[1][1] * alpha;
10994 c4f[ 6] = decal->color4f[1][2] * alpha;
10996 c4f[ 8] = decal->color4f[2][0] * alpha;
10997 c4f[ 9] = decal->color4f[2][1] * alpha;
10998 c4f[10] = decal->color4f[2][2] * alpha;
11001 t2f[0] = decal->texcoord2f[0][0];
11002 t2f[1] = decal->texcoord2f[0][1];
11003 t2f[2] = decal->texcoord2f[1][0];
11004 t2f[3] = decal->texcoord2f[1][1];
11005 t2f[4] = decal->texcoord2f[2][0];
11006 t2f[5] = decal->texcoord2f[2][1];
11008 // update vertex positions for animated models
11009 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11011 e = rsurface.modelelement3i + 3*decal->triangleindex;
11012 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11013 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11014 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11018 VectorCopy(decal->vertex3f[0], v3f);
11019 VectorCopy(decal->vertex3f[1], v3f + 3);
11020 VectorCopy(decal->vertex3f[2], v3f + 6);
11023 if (r_refdef.fogenabled)
11025 alpha = RSurf_FogVertex(v3f);
11026 VectorScale(c4f, alpha, c4f);
11027 alpha = RSurf_FogVertex(v3f + 3);
11028 VectorScale(c4f + 4, alpha, c4f + 4);
11029 alpha = RSurf_FogVertex(v3f + 6);
11030 VectorScale(c4f + 8, alpha, c4f + 8);
11041 r_refdef.stats.drawndecals += numtris;
11043 // now render the decals all at once
11044 // (this assumes they all use one particle font texture!)
11045 RSurf_ActiveCustomEntity(&rsurface.matrix, &rsurface.inversematrix, rsurface.ent_flags, rsurface.ent_shadertime, 1, 1, 1, 1, numdecals*3, decalsystem->vertex3f, decalsystem->texcoord2f, NULL, NULL, NULL, decalsystem->color4f, numtris, decalsystem->element3i, decalsystem->element3s, false, false);
11046 // R_Mesh_ResetTextureState();
11047 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11048 GL_DepthMask(false);
11049 GL_DepthRange(0, 1);
11050 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11051 GL_DepthTest(true);
11052 GL_CullFace(GL_NONE);
11053 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11054 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
11055 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11059 static void R_DrawModelDecals(void)
11063 // fade faster when there are too many decals
11064 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11065 for (i = 0;i < r_refdef.scene.numentities;i++)
11066 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11068 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11069 for (i = 0;i < r_refdef.scene.numentities;i++)
11070 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11071 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11073 R_DecalSystem_ApplySplatEntitiesQueue();
11075 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11076 for (i = 0;i < r_refdef.scene.numentities;i++)
11077 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11079 r_refdef.stats.totaldecals += numdecals;
11081 if (r_showsurfaces.integer)
11084 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11086 for (i = 0;i < r_refdef.scene.numentities;i++)
11088 if (!r_refdef.viewcache.entityvisible[i])
11090 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11091 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11095 extern cvar_t mod_collision_bih;
11096 void R_DrawDebugModel(void)
11098 entity_render_t *ent = rsurface.entity;
11099 int i, j, k, l, flagsmask;
11100 const msurface_t *surface;
11101 dp_model_t *model = ent->model;
11104 if (!sv.active && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11107 if (r_showoverdraw.value > 0)
11109 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11110 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11111 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11112 GL_DepthTest(false);
11113 GL_DepthMask(false);
11114 GL_DepthRange(0, 1);
11115 GL_BlendFunc(GL_ONE, GL_ONE);
11116 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11118 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11120 rsurface.texture = R_GetCurrentTexture(surface->texture);
11121 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11123 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11124 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11125 if (!rsurface.texture->currentlayers->depthmask)
11126 GL_Color(c, 0, 0, 1.0f);
11127 else if (ent == r_refdef.scene.worldentity)
11128 GL_Color(c, c, c, 1.0f);
11130 GL_Color(0, c, 0, 1.0f);
11131 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11135 rsurface.texture = NULL;
11138 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11140 // R_Mesh_ResetTextureState();
11141 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11142 GL_DepthRange(0, 1);
11143 GL_DepthTest(!r_showdisabledepthtest.integer);
11144 GL_DepthMask(false);
11145 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11147 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11151 qboolean cullbox = ent == r_refdef.scene.worldentity;
11152 const q3mbrush_t *brush;
11153 const bih_t *bih = &model->collision_bih;
11154 const bih_leaf_t *bihleaf;
11155 float vertex3f[3][3];
11156 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11158 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11160 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11162 switch (bihleaf->type)
11165 brush = model->brush.data_brushes + bihleaf->itemindex;
11166 if (brush->colbrushf && brush->colbrushf->numtriangles)
11168 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);
11169 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11170 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11173 case BIH_COLLISIONTRIANGLE:
11174 triangleindex = bihleaf->itemindex;
11175 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11176 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11177 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11178 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);
11179 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11180 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11182 case BIH_RENDERTRIANGLE:
11183 triangleindex = bihleaf->itemindex;
11184 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11185 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11186 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11187 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);
11188 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11189 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11195 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11197 if (r_showtris.integer && qglPolygonMode)
11199 if (r_showdisabledepthtest.integer)
11201 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11202 GL_DepthMask(false);
11206 GL_BlendFunc(GL_ONE, GL_ZERO);
11207 GL_DepthMask(true);
11209 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11210 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11212 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11214 rsurface.texture = R_GetCurrentTexture(surface->texture);
11215 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11217 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11218 if (!rsurface.texture->currentlayers->depthmask)
11219 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11220 else if (ent == r_refdef.scene.worldentity)
11221 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11223 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11224 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11228 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11229 rsurface.texture = NULL;
11232 if (r_shownormals.value != 0 && qglBegin)
11234 if (r_showdisabledepthtest.integer)
11236 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11237 GL_DepthMask(false);
11241 GL_BlendFunc(GL_ONE, GL_ZERO);
11242 GL_DepthMask(true);
11244 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11246 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11248 rsurface.texture = R_GetCurrentTexture(surface->texture);
11249 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11251 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11252 qglBegin(GL_LINES);
11253 if (r_shownormals.value < 0)
11255 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11257 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11258 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11259 qglVertex3f(v[0], v[1], v[2]);
11260 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11261 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11262 qglVertex3f(v[0], v[1], v[2]);
11265 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11267 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11269 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11270 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11271 qglVertex3f(v[0], v[1], v[2]);
11272 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11273 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11274 qglVertex3f(v[0], v[1], v[2]);
11276 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11278 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11279 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11280 qglVertex3f(v[0], v[1], v[2]);
11281 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11282 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11283 qglVertex3f(v[0], v[1], v[2]);
11285 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11287 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11288 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11289 qglVertex3f(v[0], v[1], v[2]);
11290 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11291 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11292 qglVertex3f(v[0], v[1], v[2]);
11299 rsurface.texture = NULL;
11303 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11304 int r_maxsurfacelist = 0;
11305 const msurface_t **r_surfacelist = NULL;
11306 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11308 int i, j, endj, flagsmask;
11309 dp_model_t *model = r_refdef.scene.worldmodel;
11310 msurface_t *surfaces;
11311 unsigned char *update;
11312 int numsurfacelist = 0;
11316 if (r_maxsurfacelist < model->num_surfaces)
11318 r_maxsurfacelist = model->num_surfaces;
11320 Mem_Free((msurface_t**)r_surfacelist);
11321 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11324 RSurf_ActiveWorldEntity();
11326 surfaces = model->data_surfaces;
11327 update = model->brushq1.lightmapupdateflags;
11329 // update light styles on this submodel
11330 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11332 model_brush_lightstyleinfo_t *style;
11333 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11335 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11337 int *list = style->surfacelist;
11338 style->value = r_refdef.scene.lightstylevalue[style->style];
11339 for (j = 0;j < style->numsurfaces;j++)
11340 update[list[j]] = true;
11345 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11349 R_DrawDebugModel();
11350 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11354 rsurface.lightmaptexture = NULL;
11355 rsurface.deluxemaptexture = NULL;
11356 rsurface.uselightmaptexture = false;
11357 rsurface.texture = NULL;
11358 rsurface.rtlight = NULL;
11359 numsurfacelist = 0;
11360 // add visible surfaces to draw list
11361 for (i = 0;i < model->nummodelsurfaces;i++)
11363 j = model->sortedmodelsurfaces[i];
11364 if (r_refdef.viewcache.world_surfacevisible[j])
11365 r_surfacelist[numsurfacelist++] = surfaces + j;
11367 // update lightmaps if needed
11368 if (model->brushq1.firstrender)
11370 model->brushq1.firstrender = false;
11371 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11373 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11377 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11378 if (r_refdef.viewcache.world_surfacevisible[j])
11380 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11382 // don't do anything if there were no surfaces
11383 if (!numsurfacelist)
11385 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11388 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11390 // add to stats if desired
11391 if (r_speeds.integer && !skysurfaces && !depthonly)
11393 r_refdef.stats.world_surfaces += numsurfacelist;
11394 for (j = 0;j < numsurfacelist;j++)
11395 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11398 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11401 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11403 int i, j, endj, flagsmask;
11404 dp_model_t *model = ent->model;
11405 msurface_t *surfaces;
11406 unsigned char *update;
11407 int numsurfacelist = 0;
11411 if (r_maxsurfacelist < model->num_surfaces)
11413 r_maxsurfacelist = model->num_surfaces;
11415 Mem_Free((msurface_t **)r_surfacelist);
11416 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11419 // if the model is static it doesn't matter what value we give for
11420 // wantnormals and wanttangents, so this logic uses only rules applicable
11421 // to a model, knowing that they are meaningless otherwise
11422 if (ent == r_refdef.scene.worldentity)
11423 RSurf_ActiveWorldEntity();
11424 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11425 RSurf_ActiveModelEntity(ent, false, false, false);
11427 RSurf_ActiveModelEntity(ent, true, true, true);
11428 else if (depthonly)
11430 switch (vid.renderpath)
11432 case RENDERPATH_GL20:
11433 case RENDERPATH_D3D9:
11434 case RENDERPATH_D3D10:
11435 case RENDERPATH_D3D11:
11436 case RENDERPATH_SOFT:
11437 case RENDERPATH_GLES2:
11438 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11440 case RENDERPATH_GL11:
11441 case RENDERPATH_GL13:
11442 case RENDERPATH_GLES1:
11443 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11449 switch (vid.renderpath)
11451 case RENDERPATH_GL20:
11452 case RENDERPATH_D3D9:
11453 case RENDERPATH_D3D10:
11454 case RENDERPATH_D3D11:
11455 case RENDERPATH_SOFT:
11456 case RENDERPATH_GLES2:
11457 RSurf_ActiveModelEntity(ent, true, true, false);
11459 case RENDERPATH_GL11:
11460 case RENDERPATH_GL13:
11461 case RENDERPATH_GLES1:
11462 RSurf_ActiveModelEntity(ent, true, false, false);
11467 surfaces = model->data_surfaces;
11468 update = model->brushq1.lightmapupdateflags;
11470 // update light styles
11471 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11473 model_brush_lightstyleinfo_t *style;
11474 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11476 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11478 int *list = style->surfacelist;
11479 style->value = r_refdef.scene.lightstylevalue[style->style];
11480 for (j = 0;j < style->numsurfaces;j++)
11481 update[list[j]] = true;
11486 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11490 R_DrawDebugModel();
11491 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11495 rsurface.lightmaptexture = NULL;
11496 rsurface.deluxemaptexture = NULL;
11497 rsurface.uselightmaptexture = false;
11498 rsurface.texture = NULL;
11499 rsurface.rtlight = NULL;
11500 numsurfacelist = 0;
11501 // add visible surfaces to draw list
11502 for (i = 0;i < model->nummodelsurfaces;i++)
11503 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11504 // don't do anything if there were no surfaces
11505 if (!numsurfacelist)
11507 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11510 // update lightmaps if needed
11514 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11519 R_BuildLightMap(ent, surfaces + j);
11524 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11526 R_BuildLightMap(ent, surfaces + j);
11527 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11529 // add to stats if desired
11530 if (r_speeds.integer && !skysurfaces && !depthonly)
11532 r_refdef.stats.entities_surfaces += numsurfacelist;
11533 for (j = 0;j < numsurfacelist;j++)
11534 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11537 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11540 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11542 static texture_t texture;
11543 static msurface_t surface;
11544 const msurface_t *surfacelist = &surface;
11546 // fake enough texture and surface state to render this geometry
11548 texture.update_lastrenderframe = -1; // regenerate this texture
11549 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11550 texture.currentskinframe = skinframe;
11551 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11552 texture.offsetmapping = OFFSETMAPPING_OFF;
11553 texture.offsetscale = 1;
11554 texture.specularscalemod = 1;
11555 texture.specularpowermod = 1;
11557 surface.texture = &texture;
11558 surface.num_triangles = numtriangles;
11559 surface.num_firsttriangle = firsttriangle;
11560 surface.num_vertices = numvertices;
11561 surface.num_firstvertex = firstvertex;
11564 rsurface.texture = R_GetCurrentTexture(surface.texture);
11565 rsurface.lightmaptexture = NULL;
11566 rsurface.deluxemaptexture = NULL;
11567 rsurface.uselightmaptexture = false;
11568 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11571 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)
11573 static msurface_t surface;
11574 const msurface_t *surfacelist = &surface;
11576 // fake enough texture and surface state to render this geometry
11577 surface.texture = texture;
11578 surface.num_triangles = numtriangles;
11579 surface.num_firsttriangle = firsttriangle;
11580 surface.num_vertices = numvertices;
11581 surface.num_firstvertex = firstvertex;
11584 rsurface.texture = R_GetCurrentTexture(surface.texture);
11585 rsurface.lightmaptexture = NULL;
11586 rsurface.deluxemaptexture = NULL;
11587 rsurface.uselightmaptexture = false;
11588 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);