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"};
177 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
178 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
179 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
180 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
182 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
183 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
184 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
185 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
186 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
187 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
188 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
190 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
191 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
192 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
193 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)"};
194 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
195 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
196 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
197 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
198 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
199 cvar_t r_hdr_irisadaptation_fade = {CVAR_SAVE, "r_hdr_irisadaptation_fade", "1", "fade rate at which value adjusts"};
201 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"};
203 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"};
205 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
207 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
208 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"};
209 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accordingly, 2: Make it a continuous rotation"};
210 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
211 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
212 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "5", "fake perspective effect for SPR_OVERHEAD sprites"};
213 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)"};
214 cvar_t r_overheadsprites_scalex = {CVAR_SAVE, "r_overheadsprites_scalex", "1", "additional scale for overhead sprites for x axis"};
215 cvar_t r_overheadsprites_scaley = {CVAR_SAVE, "r_overheadsprites_scaley", "1", "additional scale for overhead sprites for y axis"};
217 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
218 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"};
220 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."};
222 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)"};
224 extern cvar_t v_glslgamma;
226 extern qboolean v_flipped_state;
228 static struct r_bloomstate_s
233 int bloomwidth, bloomheight;
235 textype_t texturetype;
236 int viewfbo; // used to check if r_viewfbo cvar has changed
238 int fbo_framebuffer; // non-zero if r_viewfbo is enabled and working
239 rtexture_t *texture_framebuffercolor; // non-NULL if fbo_screen is non-zero
240 rtexture_t *texture_framebufferdepth; // non-NULL if fbo_screen is non-zero
242 int screentexturewidth, screentextureheight;
243 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
245 int bloomtexturewidth, bloomtextureheight;
246 rtexture_t *texture_bloom;
248 // arrays for rendering the screen passes
249 float screentexcoord2f[8];
250 float bloomtexcoord2f[8];
251 float offsettexcoord2f[8];
253 r_viewport_t viewport;
257 r_waterstate_t r_waterstate;
259 /// shadow volume bsp struct with automatically growing nodes buffer
262 rtexture_t *r_texture_blanknormalmap;
263 rtexture_t *r_texture_white;
264 rtexture_t *r_texture_grey128;
265 rtexture_t *r_texture_black;
266 rtexture_t *r_texture_notexture;
267 rtexture_t *r_texture_whitecube;
268 rtexture_t *r_texture_normalizationcube;
269 rtexture_t *r_texture_fogattenuation;
270 rtexture_t *r_texture_fogheighttexture;
271 rtexture_t *r_texture_gammaramps;
272 unsigned int r_texture_gammaramps_serial;
273 //rtexture_t *r_texture_fogintensity;
274 rtexture_t *r_texture_reflectcube;
276 // TODO: hash lookups?
277 typedef struct cubemapinfo_s
284 int r_texture_numcubemaps;
285 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
287 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
288 unsigned int r_numqueries;
289 unsigned int r_maxqueries;
291 typedef struct r_qwskincache_s
293 char name[MAX_QPATH];
294 skinframe_t *skinframe;
298 static r_qwskincache_t *r_qwskincache;
299 static int r_qwskincache_size;
301 /// vertex coordinates for a quad that covers the screen exactly
302 extern const float r_screenvertex3f[12];
303 extern const float r_d3dscreenvertex3f[12];
304 const float r_screenvertex3f[12] =
311 const float r_d3dscreenvertex3f[12] =
319 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
322 for (i = 0;i < verts;i++)
333 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
336 for (i = 0;i < verts;i++)
346 // FIXME: move this to client?
349 if (gamemode == GAME_NEHAHRA)
351 Cvar_Set("gl_fogenable", "0");
352 Cvar_Set("gl_fogdensity", "0.2");
353 Cvar_Set("gl_fogred", "0.3");
354 Cvar_Set("gl_foggreen", "0.3");
355 Cvar_Set("gl_fogblue", "0.3");
357 r_refdef.fog_density = 0;
358 r_refdef.fog_red = 0;
359 r_refdef.fog_green = 0;
360 r_refdef.fog_blue = 0;
361 r_refdef.fog_alpha = 1;
362 r_refdef.fog_start = 0;
363 r_refdef.fog_end = 16384;
364 r_refdef.fog_height = 1<<30;
365 r_refdef.fog_fadedepth = 128;
366 memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
369 static void R_BuildBlankTextures(void)
371 unsigned char data[4];
372 data[2] = 128; // normal X
373 data[1] = 128; // normal Y
374 data[0] = 255; // normal Z
375 data[3] = 128; // height
376 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
381 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
386 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
391 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
394 static void R_BuildNoTexture(void)
397 unsigned char pix[16][16][4];
398 // this makes a light grey/dark grey checkerboard texture
399 for (y = 0;y < 16;y++)
401 for (x = 0;x < 16;x++)
403 if ((y < 8) ^ (x < 8))
419 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
422 static void R_BuildWhiteCube(void)
424 unsigned char data[6*1*1*4];
425 memset(data, 255, sizeof(data));
426 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
429 static void R_BuildNormalizationCube(void)
433 vec_t s, t, intensity;
436 data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
437 for (side = 0;side < 6;side++)
439 for (y = 0;y < NORMSIZE;y++)
441 for (x = 0;x < NORMSIZE;x++)
443 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
444 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
479 intensity = 127.0f / sqrt(DotProduct(v, v));
480 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
481 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
482 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
483 data[((side*64+y)*64+x)*4+3] = 255;
487 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
491 static void R_BuildFogTexture(void)
495 unsigned char data1[FOGWIDTH][4];
496 //unsigned char data2[FOGWIDTH][4];
499 r_refdef.fogmasktable_start = r_refdef.fog_start;
500 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
501 r_refdef.fogmasktable_range = r_refdef.fogrange;
502 r_refdef.fogmasktable_density = r_refdef.fog_density;
504 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
505 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
507 d = (x * r - r_refdef.fogmasktable_start);
508 if(developer_extra.integer)
509 Con_DPrintf("%f ", d);
511 if (r_fog_exp2.integer)
512 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
514 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
515 if(developer_extra.integer)
516 Con_DPrintf(" : %f ", alpha);
517 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
518 if(developer_extra.integer)
519 Con_DPrintf(" = %f\n", alpha);
520 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
523 for (x = 0;x < FOGWIDTH;x++)
525 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
530 //data2[x][0] = 255 - b;
531 //data2[x][1] = 255 - b;
532 //data2[x][2] = 255 - b;
535 if (r_texture_fogattenuation)
537 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
538 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
542 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
543 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
547 static void R_BuildFogHeightTexture(void)
549 unsigned char *inpixels;
557 strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
558 if (r_refdef.fogheighttexturename[0])
559 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
562 r_refdef.fog_height_tablesize = 0;
563 if (r_texture_fogheighttexture)
564 R_FreeTexture(r_texture_fogheighttexture);
565 r_texture_fogheighttexture = NULL;
566 if (r_refdef.fog_height_table2d)
567 Mem_Free(r_refdef.fog_height_table2d);
568 r_refdef.fog_height_table2d = NULL;
569 if (r_refdef.fog_height_table1d)
570 Mem_Free(r_refdef.fog_height_table1d);
571 r_refdef.fog_height_table1d = NULL;
575 r_refdef.fog_height_tablesize = size;
576 r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
577 r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
578 memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
580 // LordHavoc: now the magic - what is that table2d for? it is a cooked
581 // average fog color table accounting for every fog layer between a point
582 // and the camera. (Note: attenuation is handled separately!)
583 for (y = 0;y < size;y++)
585 for (x = 0;x < size;x++)
591 for (j = x;j <= y;j++)
593 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
599 for (j = x;j >= y;j--)
601 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
606 r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
607 r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
608 r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
609 r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
612 r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
615 //=======================================================================================================================================================
617 static const char *builtinshaderstring =
618 #include "shader_glsl.h"
621 const char *builtinhlslshaderstring =
622 #include "shader_hlsl.h"
625 char *glslshaderstring = NULL;
626 char *hlslshaderstring = NULL;
628 //=======================================================================================================================================================
630 typedef struct shaderpermutationinfo_s
635 shaderpermutationinfo_t;
637 typedef struct shadermodeinfo_s
639 const char *vertexfilename;
640 const char *geometryfilename;
641 const char *fragmentfilename;
647 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
648 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
650 {"#define USEDIFFUSE\n", " diffuse"},
651 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
652 {"#define USEVIEWTINT\n", " viewtint"},
653 {"#define USECOLORMAPPING\n", " colormapping"},
654 {"#define USESATURATION\n", " saturation"},
655 {"#define USEFOGINSIDE\n", " foginside"},
656 {"#define USEFOGOUTSIDE\n", " fogoutside"},
657 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
658 {"#define USEFOGALPHAHACK\n", " fogalphahack"},
659 {"#define USEGAMMARAMPS\n", " gammaramps"},
660 {"#define USECUBEFILTER\n", " cubefilter"},
661 {"#define USEGLOW\n", " glow"},
662 {"#define USEBLOOM\n", " bloom"},
663 {"#define USESPECULAR\n", " specular"},
664 {"#define USEPOSTPROCESSING\n", " postprocessing"},
665 {"#define USEREFLECTION\n", " reflection"},
666 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
667 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
668 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
669 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
670 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
671 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
672 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
673 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
674 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
675 {"#define USEALPHAKILL\n", " alphakill"},
676 {"#define USEREFLECTCUBE\n", " reflectcube"},
677 {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
678 {"#define USEBOUNCEGRID\n", " bouncegrid"},
679 {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
682 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
683 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
685 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
686 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
687 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
688 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
689 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
690 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
691 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
692 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
693 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
694 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
695 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
696 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
697 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
698 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
699 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
700 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
703 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
705 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
706 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
707 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
708 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
709 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
710 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
711 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
712 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
713 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
714 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
715 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
716 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
717 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
718 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
719 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
720 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
723 struct r_glsl_permutation_s;
724 typedef struct r_glsl_permutation_s
727 struct r_glsl_permutation_s *hashnext;
729 unsigned int permutation;
731 /// indicates if we have tried compiling this permutation already
733 /// 0 if compilation failed
735 // texture units assigned to each detected uniform
736 int tex_Texture_First;
737 int tex_Texture_Second;
738 int tex_Texture_GammaRamps;
739 int tex_Texture_Normal;
740 int tex_Texture_Color;
741 int tex_Texture_Gloss;
742 int tex_Texture_Glow;
743 int tex_Texture_SecondaryNormal;
744 int tex_Texture_SecondaryColor;
745 int tex_Texture_SecondaryGloss;
746 int tex_Texture_SecondaryGlow;
747 int tex_Texture_Pants;
748 int tex_Texture_Shirt;
749 int tex_Texture_FogHeightTexture;
750 int tex_Texture_FogMask;
751 int tex_Texture_Lightmap;
752 int tex_Texture_Deluxemap;
753 int tex_Texture_Attenuation;
754 int tex_Texture_Cube;
755 int tex_Texture_Refraction;
756 int tex_Texture_Reflection;
757 int tex_Texture_ShadowMap2D;
758 int tex_Texture_CubeProjection;
759 int tex_Texture_ScreenDepth;
760 int tex_Texture_ScreenNormalMap;
761 int tex_Texture_ScreenDiffuse;
762 int tex_Texture_ScreenSpecular;
763 int tex_Texture_ReflectMask;
764 int tex_Texture_ReflectCube;
765 int tex_Texture_BounceGrid;
766 /// locations of detected uniforms in program object, or -1 if not found
767 int loc_Texture_First;
768 int loc_Texture_Second;
769 int loc_Texture_GammaRamps;
770 int loc_Texture_Normal;
771 int loc_Texture_Color;
772 int loc_Texture_Gloss;
773 int loc_Texture_Glow;
774 int loc_Texture_SecondaryNormal;
775 int loc_Texture_SecondaryColor;
776 int loc_Texture_SecondaryGloss;
777 int loc_Texture_SecondaryGlow;
778 int loc_Texture_Pants;
779 int loc_Texture_Shirt;
780 int loc_Texture_FogHeightTexture;
781 int loc_Texture_FogMask;
782 int loc_Texture_Lightmap;
783 int loc_Texture_Deluxemap;
784 int loc_Texture_Attenuation;
785 int loc_Texture_Cube;
786 int loc_Texture_Refraction;
787 int loc_Texture_Reflection;
788 int loc_Texture_ShadowMap2D;
789 int loc_Texture_CubeProjection;
790 int loc_Texture_ScreenDepth;
791 int loc_Texture_ScreenNormalMap;
792 int loc_Texture_ScreenDiffuse;
793 int loc_Texture_ScreenSpecular;
794 int loc_Texture_ReflectMask;
795 int loc_Texture_ReflectCube;
796 int loc_Texture_BounceGrid;
798 int loc_BloomBlur_Parameters;
800 int loc_Color_Ambient;
801 int loc_Color_Diffuse;
802 int loc_Color_Specular;
806 int loc_DeferredColor_Ambient;
807 int loc_DeferredColor_Diffuse;
808 int loc_DeferredColor_Specular;
809 int loc_DeferredMod_Diffuse;
810 int loc_DeferredMod_Specular;
811 int loc_DistortScaleRefractReflect;
814 int loc_FogHeightFade;
816 int loc_FogPlaneViewDist;
817 int loc_FogRangeRecip;
820 int loc_LightPosition;
821 int loc_OffsetMapping_ScaleSteps;
823 int loc_ReflectColor;
824 int loc_ReflectFactor;
825 int loc_ReflectOffset;
826 int loc_RefractColor;
828 int loc_ScreenCenterRefractReflect;
829 int loc_ScreenScaleRefractReflect;
830 int loc_ScreenToDepth;
831 int loc_ShadowMap_Parameters;
832 int loc_ShadowMap_TextureScale;
833 int loc_SpecularPower;
838 int loc_ViewTintColor;
840 int loc_ModelToLight;
842 int loc_BackgroundTexMatrix;
843 int loc_ModelViewProjectionMatrix;
844 int loc_ModelViewMatrix;
845 int loc_PixelToScreenTexCoord;
846 int loc_ModelToReflectCube;
847 int loc_ShadowMapMatrix;
848 int loc_BloomColorSubtract;
849 int loc_NormalmapScrollBlend;
850 int loc_BounceGridMatrix;
851 int loc_BounceGridIntensity;
853 r_glsl_permutation_t;
855 #define SHADERPERMUTATION_HASHSIZE 256
858 // non-degradable "lightweight" shader parameters to keep the permutations simpler
859 // these can NOT degrade! only use for simple stuff
862 SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
863 SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
864 SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
865 SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
866 SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
867 SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5, ///< postprocess uservec4 is enabled
868 SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6 // use both alpha layers while blending materials, allows more advanced microblending
870 #define SHADERSTATICPARMS_COUNT 7
872 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
873 static int shaderstaticparms_count = 0;
875 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
876 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
877 qboolean R_CompileShader_CheckStaticParms(void)
879 static int r_compileshader_staticparms_save[1];
880 memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
881 memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
884 if (r_glsl_saturation_redcompensate.integer)
885 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
886 if (r_glsl_vertextextureblend_usebothalphas.integer)
887 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
888 if (r_shadow_glossexact.integer)
889 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
890 if (r_glsl_postprocess.integer)
892 if (r_glsl_postprocess_uservec1_enable.integer)
893 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
894 if (r_glsl_postprocess_uservec2_enable.integer)
895 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
896 if (r_glsl_postprocess_uservec3_enable.integer)
897 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
898 if (r_glsl_postprocess_uservec4_enable.integer)
899 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
901 return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
904 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
905 if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
906 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
908 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
909 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
911 shaderstaticparms_count = 0;
914 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
915 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
916 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
917 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
918 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
919 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
920 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
923 /// information about each possible shader permutation
924 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
925 /// currently selected permutation
926 r_glsl_permutation_t *r_glsl_permutation;
927 /// storage for permutations linked in the hash table
928 memexpandablearray_t r_glsl_permutationarray;
930 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
932 //unsigned int hashdepth = 0;
933 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
934 r_glsl_permutation_t *p;
935 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
937 if (p->mode == mode && p->permutation == permutation)
939 //if (hashdepth > 10)
940 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
945 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
947 p->permutation = permutation;
948 p->hashnext = r_glsl_permutationhash[mode][hashindex];
949 r_glsl_permutationhash[mode][hashindex] = p;
950 //if (hashdepth > 10)
951 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
955 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
958 if (!filename || !filename[0])
960 if (!strcmp(filename, "glsl/default.glsl"))
962 if (!glslshaderstring)
964 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
965 if (glslshaderstring)
966 Con_DPrintf("Loading shaders from file %s...\n", filename);
968 glslshaderstring = (char *)builtinshaderstring;
970 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
971 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
974 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
977 if (printfromdisknotice)
978 Con_DPrintf("from disk %s... ", filename);
984 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
988 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
989 char *vertexstring, *geometrystring, *fragmentstring;
990 char permutationname[256];
991 int vertstrings_count = 0;
992 int geomstrings_count = 0;
993 int fragstrings_count = 0;
994 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
995 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
996 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1003 permutationname[0] = 0;
1004 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
1005 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1006 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1008 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1010 // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1011 if(vid.support.gl20shaders130)
1013 vertstrings_list[vertstrings_count++] = "#version 130\n";
1014 geomstrings_list[geomstrings_count++] = "#version 130\n";
1015 fragstrings_list[fragstrings_count++] = "#version 130\n";
1016 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1017 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1018 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1021 // the first pretext is which type of shader to compile as
1022 // (later these will all be bound together as a program object)
1023 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1024 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1025 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1027 // the second pretext is the mode (for example a light source)
1028 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1029 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1030 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1031 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1033 // now add all the permutation pretexts
1034 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1036 if (permutation & (1<<i))
1038 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1039 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1040 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1041 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1045 // keep line numbers correct
1046 vertstrings_list[vertstrings_count++] = "\n";
1047 geomstrings_list[geomstrings_count++] = "\n";
1048 fragstrings_list[fragstrings_count++] = "\n";
1053 R_CompileShader_AddStaticParms(mode, permutation);
1054 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1055 vertstrings_count += shaderstaticparms_count;
1056 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1057 geomstrings_count += shaderstaticparms_count;
1058 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1059 fragstrings_count += shaderstaticparms_count;
1061 // now append the shader text itself
1062 vertstrings_list[vertstrings_count++] = vertexstring;
1063 geomstrings_list[geomstrings_count++] = geometrystring;
1064 fragstrings_list[fragstrings_count++] = fragmentstring;
1066 // if any sources were NULL, clear the respective list
1068 vertstrings_count = 0;
1069 if (!geometrystring)
1070 geomstrings_count = 0;
1071 if (!fragmentstring)
1072 fragstrings_count = 0;
1074 // compile the shader program
1075 if (vertstrings_count + geomstrings_count + fragstrings_count)
1076 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1080 qglUseProgram(p->program);CHECKGLERROR
1081 // look up all the uniform variable names we care about, so we don't
1082 // have to look them up every time we set them
1084 p->loc_Texture_First = qglGetUniformLocation(p->program, "Texture_First");
1085 p->loc_Texture_Second = qglGetUniformLocation(p->program, "Texture_Second");
1086 p->loc_Texture_GammaRamps = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1087 p->loc_Texture_Normal = qglGetUniformLocation(p->program, "Texture_Normal");
1088 p->loc_Texture_Color = qglGetUniformLocation(p->program, "Texture_Color");
1089 p->loc_Texture_Gloss = qglGetUniformLocation(p->program, "Texture_Gloss");
1090 p->loc_Texture_Glow = qglGetUniformLocation(p->program, "Texture_Glow");
1091 p->loc_Texture_SecondaryNormal = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1092 p->loc_Texture_SecondaryColor = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1093 p->loc_Texture_SecondaryGloss = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1094 p->loc_Texture_SecondaryGlow = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1095 p->loc_Texture_Pants = qglGetUniformLocation(p->program, "Texture_Pants");
1096 p->loc_Texture_Shirt = qglGetUniformLocation(p->program, "Texture_Shirt");
1097 p->loc_Texture_FogHeightTexture = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1098 p->loc_Texture_FogMask = qglGetUniformLocation(p->program, "Texture_FogMask");
1099 p->loc_Texture_Lightmap = qglGetUniformLocation(p->program, "Texture_Lightmap");
1100 p->loc_Texture_Deluxemap = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1101 p->loc_Texture_Attenuation = qglGetUniformLocation(p->program, "Texture_Attenuation");
1102 p->loc_Texture_Cube = qglGetUniformLocation(p->program, "Texture_Cube");
1103 p->loc_Texture_Refraction = qglGetUniformLocation(p->program, "Texture_Refraction");
1104 p->loc_Texture_Reflection = qglGetUniformLocation(p->program, "Texture_Reflection");
1105 p->loc_Texture_ShadowMap2D = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1106 p->loc_Texture_CubeProjection = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1107 p->loc_Texture_ScreenDepth = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1108 p->loc_Texture_ScreenNormalMap = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1109 p->loc_Texture_ScreenDiffuse = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1110 p->loc_Texture_ScreenSpecular = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1111 p->loc_Texture_ReflectMask = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1112 p->loc_Texture_ReflectCube = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1113 p->loc_Texture_BounceGrid = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1114 p->loc_Alpha = qglGetUniformLocation(p->program, "Alpha");
1115 p->loc_BloomBlur_Parameters = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1116 p->loc_ClientTime = qglGetUniformLocation(p->program, "ClientTime");
1117 p->loc_Color_Ambient = qglGetUniformLocation(p->program, "Color_Ambient");
1118 p->loc_Color_Diffuse = qglGetUniformLocation(p->program, "Color_Diffuse");
1119 p->loc_Color_Specular = qglGetUniformLocation(p->program, "Color_Specular");
1120 p->loc_Color_Glow = qglGetUniformLocation(p->program, "Color_Glow");
1121 p->loc_Color_Pants = qglGetUniformLocation(p->program, "Color_Pants");
1122 p->loc_Color_Shirt = qglGetUniformLocation(p->program, "Color_Shirt");
1123 p->loc_DeferredColor_Ambient = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1124 p->loc_DeferredColor_Diffuse = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1125 p->loc_DeferredColor_Specular = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1126 p->loc_DeferredMod_Diffuse = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1127 p->loc_DeferredMod_Specular = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1128 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1129 p->loc_EyePosition = qglGetUniformLocation(p->program, "EyePosition");
1130 p->loc_FogColor = qglGetUniformLocation(p->program, "FogColor");
1131 p->loc_FogHeightFade = qglGetUniformLocation(p->program, "FogHeightFade");
1132 p->loc_FogPlane = qglGetUniformLocation(p->program, "FogPlane");
1133 p->loc_FogPlaneViewDist = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1134 p->loc_FogRangeRecip = qglGetUniformLocation(p->program, "FogRangeRecip");
1135 p->loc_LightColor = qglGetUniformLocation(p->program, "LightColor");
1136 p->loc_LightDir = qglGetUniformLocation(p->program, "LightDir");
1137 p->loc_LightPosition = qglGetUniformLocation(p->program, "LightPosition");
1138 p->loc_OffsetMapping_ScaleSteps = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1139 p->loc_PixelSize = qglGetUniformLocation(p->program, "PixelSize");
1140 p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor");
1141 p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor");
1142 p->loc_ReflectOffset = qglGetUniformLocation(p->program, "ReflectOffset");
1143 p->loc_RefractColor = qglGetUniformLocation(p->program, "RefractColor");
1144 p->loc_Saturation = qglGetUniformLocation(p->program, "Saturation");
1145 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1146 p->loc_ScreenScaleRefractReflect = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1147 p->loc_ScreenToDepth = qglGetUniformLocation(p->program, "ScreenToDepth");
1148 p->loc_ShadowMap_Parameters = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1149 p->loc_ShadowMap_TextureScale = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1150 p->loc_SpecularPower = qglGetUniformLocation(p->program, "SpecularPower");
1151 p->loc_UserVec1 = qglGetUniformLocation(p->program, "UserVec1");
1152 p->loc_UserVec2 = qglGetUniformLocation(p->program, "UserVec2");
1153 p->loc_UserVec3 = qglGetUniformLocation(p->program, "UserVec3");
1154 p->loc_UserVec4 = qglGetUniformLocation(p->program, "UserVec4");
1155 p->loc_ViewTintColor = qglGetUniformLocation(p->program, "ViewTintColor");
1156 p->loc_ViewToLight = qglGetUniformLocation(p->program, "ViewToLight");
1157 p->loc_ModelToLight = qglGetUniformLocation(p->program, "ModelToLight");
1158 p->loc_TexMatrix = qglGetUniformLocation(p->program, "TexMatrix");
1159 p->loc_BackgroundTexMatrix = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1160 p->loc_ModelViewMatrix = qglGetUniformLocation(p->program, "ModelViewMatrix");
1161 p->loc_ModelViewProjectionMatrix = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1162 p->loc_PixelToScreenTexCoord = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1163 p->loc_ModelToReflectCube = qglGetUniformLocation(p->program, "ModelToReflectCube");
1164 p->loc_ShadowMapMatrix = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1165 p->loc_BloomColorSubtract = qglGetUniformLocation(p->program, "BloomColorSubtract");
1166 p->loc_NormalmapScrollBlend = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1167 p->loc_BounceGridMatrix = qglGetUniformLocation(p->program, "BounceGridMatrix");
1168 p->loc_BounceGridIntensity = qglGetUniformLocation(p->program, "BounceGridIntensity");
1169 // initialize the samplers to refer to the texture units we use
1170 p->tex_Texture_First = -1;
1171 p->tex_Texture_Second = -1;
1172 p->tex_Texture_GammaRamps = -1;
1173 p->tex_Texture_Normal = -1;
1174 p->tex_Texture_Color = -1;
1175 p->tex_Texture_Gloss = -1;
1176 p->tex_Texture_Glow = -1;
1177 p->tex_Texture_SecondaryNormal = -1;
1178 p->tex_Texture_SecondaryColor = -1;
1179 p->tex_Texture_SecondaryGloss = -1;
1180 p->tex_Texture_SecondaryGlow = -1;
1181 p->tex_Texture_Pants = -1;
1182 p->tex_Texture_Shirt = -1;
1183 p->tex_Texture_FogHeightTexture = -1;
1184 p->tex_Texture_FogMask = -1;
1185 p->tex_Texture_Lightmap = -1;
1186 p->tex_Texture_Deluxemap = -1;
1187 p->tex_Texture_Attenuation = -1;
1188 p->tex_Texture_Cube = -1;
1189 p->tex_Texture_Refraction = -1;
1190 p->tex_Texture_Reflection = -1;
1191 p->tex_Texture_ShadowMap2D = -1;
1192 p->tex_Texture_CubeProjection = -1;
1193 p->tex_Texture_ScreenDepth = -1;
1194 p->tex_Texture_ScreenNormalMap = -1;
1195 p->tex_Texture_ScreenDiffuse = -1;
1196 p->tex_Texture_ScreenSpecular = -1;
1197 p->tex_Texture_ReflectMask = -1;
1198 p->tex_Texture_ReflectCube = -1;
1199 p->tex_Texture_BounceGrid = -1;
1201 if (p->loc_Texture_First >= 0) {p->tex_Texture_First = sampler;qglUniform1i(p->loc_Texture_First , sampler);sampler++;}
1202 if (p->loc_Texture_Second >= 0) {p->tex_Texture_Second = sampler;qglUniform1i(p->loc_Texture_Second , sampler);sampler++;}
1203 if (p->loc_Texture_GammaRamps >= 0) {p->tex_Texture_GammaRamps = sampler;qglUniform1i(p->loc_Texture_GammaRamps , sampler);sampler++;}
1204 if (p->loc_Texture_Normal >= 0) {p->tex_Texture_Normal = sampler;qglUniform1i(p->loc_Texture_Normal , sampler);sampler++;}
1205 if (p->loc_Texture_Color >= 0) {p->tex_Texture_Color = sampler;qglUniform1i(p->loc_Texture_Color , sampler);sampler++;}
1206 if (p->loc_Texture_Gloss >= 0) {p->tex_Texture_Gloss = sampler;qglUniform1i(p->loc_Texture_Gloss , sampler);sampler++;}
1207 if (p->loc_Texture_Glow >= 0) {p->tex_Texture_Glow = sampler;qglUniform1i(p->loc_Texture_Glow , sampler);sampler++;}
1208 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1209 if (p->loc_Texture_SecondaryColor >= 0) {p->tex_Texture_SecondaryColor = sampler;qglUniform1i(p->loc_Texture_SecondaryColor , sampler);sampler++;}
1210 if (p->loc_Texture_SecondaryGloss >= 0) {p->tex_Texture_SecondaryGloss = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss , sampler);sampler++;}
1211 if (p->loc_Texture_SecondaryGlow >= 0) {p->tex_Texture_SecondaryGlow = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow , sampler);sampler++;}
1212 if (p->loc_Texture_Pants >= 0) {p->tex_Texture_Pants = sampler;qglUniform1i(p->loc_Texture_Pants , sampler);sampler++;}
1213 if (p->loc_Texture_Shirt >= 0) {p->tex_Texture_Shirt = sampler;qglUniform1i(p->loc_Texture_Shirt , sampler);sampler++;}
1214 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1215 if (p->loc_Texture_FogMask >= 0) {p->tex_Texture_FogMask = sampler;qglUniform1i(p->loc_Texture_FogMask , sampler);sampler++;}
1216 if (p->loc_Texture_Lightmap >= 0) {p->tex_Texture_Lightmap = sampler;qglUniform1i(p->loc_Texture_Lightmap , sampler);sampler++;}
1217 if (p->loc_Texture_Deluxemap >= 0) {p->tex_Texture_Deluxemap = sampler;qglUniform1i(p->loc_Texture_Deluxemap , sampler);sampler++;}
1218 if (p->loc_Texture_Attenuation >= 0) {p->tex_Texture_Attenuation = sampler;qglUniform1i(p->loc_Texture_Attenuation , sampler);sampler++;}
1219 if (p->loc_Texture_Cube >= 0) {p->tex_Texture_Cube = sampler;qglUniform1i(p->loc_Texture_Cube , sampler);sampler++;}
1220 if (p->loc_Texture_Refraction >= 0) {p->tex_Texture_Refraction = sampler;qglUniform1i(p->loc_Texture_Refraction , sampler);sampler++;}
1221 if (p->loc_Texture_Reflection >= 0) {p->tex_Texture_Reflection = sampler;qglUniform1i(p->loc_Texture_Reflection , sampler);sampler++;}
1222 if (p->loc_Texture_ShadowMap2D >= 0) {p->tex_Texture_ShadowMap2D = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D , sampler);sampler++;}
1223 if (p->loc_Texture_CubeProjection >= 0) {p->tex_Texture_CubeProjection = sampler;qglUniform1i(p->loc_Texture_CubeProjection , sampler);sampler++;}
1224 if (p->loc_Texture_ScreenDepth >= 0) {p->tex_Texture_ScreenDepth = sampler;qglUniform1i(p->loc_Texture_ScreenDepth , sampler);sampler++;}
1225 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1226 if (p->loc_Texture_ScreenDiffuse >= 0) {p->tex_Texture_ScreenDiffuse = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse , sampler);sampler++;}
1227 if (p->loc_Texture_ScreenSpecular >= 0) {p->tex_Texture_ScreenSpecular = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular , sampler);sampler++;}
1228 if (p->loc_Texture_ReflectMask >= 0) {p->tex_Texture_ReflectMask = sampler;qglUniform1i(p->loc_Texture_ReflectMask , sampler);sampler++;}
1229 if (p->loc_Texture_ReflectCube >= 0) {p->tex_Texture_ReflectCube = sampler;qglUniform1i(p->loc_Texture_ReflectCube , sampler);sampler++;}
1230 if (p->loc_Texture_BounceGrid >= 0) {p->tex_Texture_BounceGrid = sampler;qglUniform1i(p->loc_Texture_BounceGrid , sampler);sampler++;}
1232 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1235 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
1239 Mem_Free(vertexstring);
1241 Mem_Free(geometrystring);
1243 Mem_Free(fragmentstring);
1246 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1248 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1249 if (r_glsl_permutation != perm)
1251 r_glsl_permutation = perm;
1252 if (!r_glsl_permutation->program)
1254 if (!r_glsl_permutation->compiled)
1255 R_GLSL_CompilePermutation(perm, mode, permutation);
1256 if (!r_glsl_permutation->program)
1258 // remove features until we find a valid permutation
1260 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1262 // reduce i more quickly whenever it would not remove any bits
1263 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1264 if (!(permutation & j))
1267 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1268 if (!r_glsl_permutation->compiled)
1269 R_GLSL_CompilePermutation(perm, mode, permutation);
1270 if (r_glsl_permutation->program)
1273 if (i >= SHADERPERMUTATION_COUNT)
1275 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1276 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1277 qglUseProgram(0);CHECKGLERROR
1278 return; // no bit left to clear, entire mode is broken
1283 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1285 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1286 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1287 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1294 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1295 extern D3DCAPS9 vid_d3d9caps;
1298 struct r_hlsl_permutation_s;
1299 typedef struct r_hlsl_permutation_s
1301 /// hash lookup data
1302 struct r_hlsl_permutation_s *hashnext;
1304 unsigned int permutation;
1306 /// indicates if we have tried compiling this permutation already
1308 /// NULL if compilation failed
1309 IDirect3DVertexShader9 *vertexshader;
1310 IDirect3DPixelShader9 *pixelshader;
1312 r_hlsl_permutation_t;
1314 typedef enum D3DVSREGISTER_e
1316 D3DVSREGISTER_TexMatrix = 0, // float4x4
1317 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1318 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1319 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1320 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1321 D3DVSREGISTER_ModelToLight = 20, // float4x4
1322 D3DVSREGISTER_EyePosition = 24,
1323 D3DVSREGISTER_FogPlane = 25,
1324 D3DVSREGISTER_LightDir = 26,
1325 D3DVSREGISTER_LightPosition = 27,
1329 typedef enum D3DPSREGISTER_e
1331 D3DPSREGISTER_Alpha = 0,
1332 D3DPSREGISTER_BloomBlur_Parameters = 1,
1333 D3DPSREGISTER_ClientTime = 2,
1334 D3DPSREGISTER_Color_Ambient = 3,
1335 D3DPSREGISTER_Color_Diffuse = 4,
1336 D3DPSREGISTER_Color_Specular = 5,
1337 D3DPSREGISTER_Color_Glow = 6,
1338 D3DPSREGISTER_Color_Pants = 7,
1339 D3DPSREGISTER_Color_Shirt = 8,
1340 D3DPSREGISTER_DeferredColor_Ambient = 9,
1341 D3DPSREGISTER_DeferredColor_Diffuse = 10,
1342 D3DPSREGISTER_DeferredColor_Specular = 11,
1343 D3DPSREGISTER_DeferredMod_Diffuse = 12,
1344 D3DPSREGISTER_DeferredMod_Specular = 13,
1345 D3DPSREGISTER_DistortScaleRefractReflect = 14,
1346 D3DPSREGISTER_EyePosition = 15, // unused
1347 D3DPSREGISTER_FogColor = 16,
1348 D3DPSREGISTER_FogHeightFade = 17,
1349 D3DPSREGISTER_FogPlane = 18,
1350 D3DPSREGISTER_FogPlaneViewDist = 19,
1351 D3DPSREGISTER_FogRangeRecip = 20,
1352 D3DPSREGISTER_LightColor = 21,
1353 D3DPSREGISTER_LightDir = 22, // unused
1354 D3DPSREGISTER_LightPosition = 23,
1355 D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1356 D3DPSREGISTER_PixelSize = 25,
1357 D3DPSREGISTER_ReflectColor = 26,
1358 D3DPSREGISTER_ReflectFactor = 27,
1359 D3DPSREGISTER_ReflectOffset = 28,
1360 D3DPSREGISTER_RefractColor = 29,
1361 D3DPSREGISTER_Saturation = 30,
1362 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1363 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1364 D3DPSREGISTER_ScreenToDepth = 33,
1365 D3DPSREGISTER_ShadowMap_Parameters = 34,
1366 D3DPSREGISTER_ShadowMap_TextureScale = 35,
1367 D3DPSREGISTER_SpecularPower = 36,
1368 D3DPSREGISTER_UserVec1 = 37,
1369 D3DPSREGISTER_UserVec2 = 38,
1370 D3DPSREGISTER_UserVec3 = 39,
1371 D3DPSREGISTER_UserVec4 = 40,
1372 D3DPSREGISTER_ViewTintColor = 41,
1373 D3DPSREGISTER_PixelToScreenTexCoord = 42,
1374 D3DPSREGISTER_BloomColorSubtract = 43,
1375 D3DPSREGISTER_ViewToLight = 44, // float4x4
1376 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1377 D3DPSREGISTER_NormalmapScrollBlend = 52,
1382 /// information about each possible shader permutation
1383 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1384 /// currently selected permutation
1385 r_hlsl_permutation_t *r_hlsl_permutation;
1386 /// storage for permutations linked in the hash table
1387 memexpandablearray_t r_hlsl_permutationarray;
1389 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1391 //unsigned int hashdepth = 0;
1392 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1393 r_hlsl_permutation_t *p;
1394 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1396 if (p->mode == mode && p->permutation == permutation)
1398 //if (hashdepth > 10)
1399 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1404 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1406 p->permutation = permutation;
1407 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1408 r_hlsl_permutationhash[mode][hashindex] = p;
1409 //if (hashdepth > 10)
1410 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1414 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1417 if (!filename || !filename[0])
1419 if (!strcmp(filename, "hlsl/default.hlsl"))
1421 if (!hlslshaderstring)
1423 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1424 if (hlslshaderstring)
1425 Con_DPrintf("Loading shaders from file %s...\n", filename);
1427 hlslshaderstring = (char *)builtinhlslshaderstring;
1429 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1430 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1431 return shaderstring;
1433 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1436 if (printfromdisknotice)
1437 Con_DPrintf("from disk %s... ", filename);
1438 return shaderstring;
1440 return shaderstring;
1444 //#include <d3dx9shader.h>
1445 //#include <d3dx9mesh.h>
1447 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1449 DWORD *vsbin = NULL;
1450 DWORD *psbin = NULL;
1451 fs_offset_t vsbinsize;
1452 fs_offset_t psbinsize;
1453 // IDirect3DVertexShader9 *vs = NULL;
1454 // IDirect3DPixelShader9 *ps = NULL;
1455 ID3DXBuffer *vslog = NULL;
1456 ID3DXBuffer *vsbuffer = NULL;
1457 ID3DXConstantTable *vsconstanttable = NULL;
1458 ID3DXBuffer *pslog = NULL;
1459 ID3DXBuffer *psbuffer = NULL;
1460 ID3DXConstantTable *psconstanttable = NULL;
1463 char temp[MAX_INPUTLINE];
1464 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1465 qboolean debugshader = gl_paranoid.integer != 0;
1466 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1467 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1470 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1471 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1473 if ((!vsbin && vertstring) || (!psbin && fragstring))
1475 const char* dllnames_d3dx9 [] =
1499 dllhandle_t d3dx9_dll = NULL;
1500 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1501 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1502 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1503 dllfunction_t d3dx9_dllfuncs[] =
1505 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
1506 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
1507 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
1510 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1512 DWORD shaderflags = 0;
1514 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1515 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1516 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1517 if (vertstring && vertstring[0])
1521 // vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1522 // FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1523 FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1524 vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1527 vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1530 vsbinsize = vsbuffer->GetBufferSize();
1531 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1532 memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1533 vsbuffer->Release();
1537 strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1538 Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1542 if (fragstring && fragstring[0])
1546 // psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1547 // FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1548 FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1549 psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1552 psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1555 psbinsize = psbuffer->GetBufferSize();
1556 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1557 memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1558 psbuffer->Release();
1562 strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1563 Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1567 Sys_UnloadLibrary(&d3dx9_dll);
1570 Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1574 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1575 if (FAILED(vsresult))
1576 Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1577 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1578 if (FAILED(psresult))
1579 Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1581 // free the shader data
1582 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1583 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1586 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1589 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1590 int vertstring_length = 0;
1591 int geomstring_length = 0;
1592 int fragstring_length = 0;
1594 char *vertexstring, *geometrystring, *fragmentstring;
1595 char *vertstring, *geomstring, *fragstring;
1596 char permutationname[256];
1597 char cachename[256];
1598 int vertstrings_count = 0;
1599 int geomstrings_count = 0;
1600 int fragstrings_count = 0;
1601 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1602 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1603 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1608 p->vertexshader = NULL;
1609 p->pixelshader = NULL;
1611 permutationname[0] = 0;
1613 vertexstring = R_HLSL_GetText(modeinfo->vertexfilename, true);
1614 geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1615 fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1617 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1618 strlcat(cachename, "hlsl/", sizeof(cachename));
1620 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1621 vertstrings_count = 0;
1622 geomstrings_count = 0;
1623 fragstrings_count = 0;
1624 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1625 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1626 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1628 // the first pretext is which type of shader to compile as
1629 // (later these will all be bound together as a program object)
1630 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1631 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1632 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1634 // the second pretext is the mode (for example a light source)
1635 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1636 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1637 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1638 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1639 strlcat(cachename, modeinfo->name, sizeof(cachename));
1641 // now add all the permutation pretexts
1642 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1644 if (permutation & (1<<i))
1646 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1647 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1648 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1649 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1650 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1654 // keep line numbers correct
1655 vertstrings_list[vertstrings_count++] = "\n";
1656 geomstrings_list[geomstrings_count++] = "\n";
1657 fragstrings_list[fragstrings_count++] = "\n";
1662 R_CompileShader_AddStaticParms(mode, permutation);
1663 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1664 vertstrings_count += shaderstaticparms_count;
1665 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1666 geomstrings_count += shaderstaticparms_count;
1667 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1668 fragstrings_count += shaderstaticparms_count;
1670 // replace spaces in the cachename with _ characters
1671 for (i = 0;cachename[i];i++)
1672 if (cachename[i] == ' ')
1675 // now append the shader text itself
1676 vertstrings_list[vertstrings_count++] = vertexstring;
1677 geomstrings_list[geomstrings_count++] = geometrystring;
1678 fragstrings_list[fragstrings_count++] = fragmentstring;
1680 // if any sources were NULL, clear the respective list
1682 vertstrings_count = 0;
1683 if (!geometrystring)
1684 geomstrings_count = 0;
1685 if (!fragmentstring)
1686 fragstrings_count = 0;
1688 vertstring_length = 0;
1689 for (i = 0;i < vertstrings_count;i++)
1690 vertstring_length += strlen(vertstrings_list[i]);
1691 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1692 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1693 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1695 geomstring_length = 0;
1696 for (i = 0;i < geomstrings_count;i++)
1697 geomstring_length += strlen(geomstrings_list[i]);
1698 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1699 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1700 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1702 fragstring_length = 0;
1703 for (i = 0;i < fragstrings_count;i++)
1704 fragstring_length += strlen(fragstrings_list[i]);
1705 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1706 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1707 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1709 // try to load the cached shader, or generate one
1710 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1712 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1713 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1715 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
1719 Mem_Free(vertstring);
1721 Mem_Free(geomstring);
1723 Mem_Free(fragstring);
1725 Mem_Free(vertexstring);
1727 Mem_Free(geometrystring);
1729 Mem_Free(fragmentstring);
1732 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1733 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1734 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);}
1735 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);}
1736 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);}
1737 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);}
1739 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1740 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1741 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);}
1742 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);}
1743 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);}
1744 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);}
1746 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1748 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1749 if (r_hlsl_permutation != perm)
1751 r_hlsl_permutation = perm;
1752 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1754 if (!r_hlsl_permutation->compiled)
1755 R_HLSL_CompilePermutation(perm, mode, permutation);
1756 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1758 // remove features until we find a valid permutation
1760 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1762 // reduce i more quickly whenever it would not remove any bits
1763 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1764 if (!(permutation & j))
1767 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1768 if (!r_hlsl_permutation->compiled)
1769 R_HLSL_CompilePermutation(perm, mode, permutation);
1770 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1773 if (i >= SHADERPERMUTATION_COUNT)
1775 //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1776 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1777 return; // no bit left to clear, entire mode is broken
1781 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1782 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1784 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1785 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1786 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1790 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1792 DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1793 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1794 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1795 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1798 void R_GLSL_Restart_f(void)
1800 unsigned int i, limit;
1801 if (glslshaderstring && glslshaderstring != builtinshaderstring)
1802 Mem_Free(glslshaderstring);
1803 glslshaderstring = NULL;
1804 if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1805 Mem_Free(hlslshaderstring);
1806 hlslshaderstring = NULL;
1807 switch(vid.renderpath)
1809 case RENDERPATH_D3D9:
1812 r_hlsl_permutation_t *p;
1813 r_hlsl_permutation = NULL;
1814 limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1815 for (i = 0;i < limit;i++)
1817 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1819 if (p->vertexshader)
1820 IDirect3DVertexShader9_Release(p->vertexshader);
1822 IDirect3DPixelShader9_Release(p->pixelshader);
1823 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1826 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1830 case RENDERPATH_D3D10:
1831 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1833 case RENDERPATH_D3D11:
1834 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1836 case RENDERPATH_GL20:
1837 case RENDERPATH_GLES2:
1839 r_glsl_permutation_t *p;
1840 r_glsl_permutation = NULL;
1841 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1842 for (i = 0;i < limit;i++)
1844 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1846 GL_Backend_FreeProgram(p->program);
1847 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1850 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1853 case RENDERPATH_GL11:
1854 case RENDERPATH_GL13:
1855 case RENDERPATH_GLES1:
1857 case RENDERPATH_SOFT:
1862 void R_GLSL_DumpShader_f(void)
1867 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1870 FS_Print(file, "/* The engine may define the following macros:\n");
1871 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1872 for (i = 0;i < SHADERMODE_COUNT;i++)
1873 FS_Print(file, glslshadermodeinfo[i].pretext);
1874 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1875 FS_Print(file, shaderpermutationinfo[i].pretext);
1876 FS_Print(file, "*/\n");
1877 FS_Print(file, builtinshaderstring);
1879 Con_Printf("glsl/default.glsl written\n");
1882 Con_Printf("failed to write to glsl/default.glsl\n");
1884 file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1887 FS_Print(file, "/* The engine may define the following macros:\n");
1888 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1889 for (i = 0;i < SHADERMODE_COUNT;i++)
1890 FS_Print(file, hlslshadermodeinfo[i].pretext);
1891 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1892 FS_Print(file, shaderpermutationinfo[i].pretext);
1893 FS_Print(file, "*/\n");
1894 FS_Print(file, builtinhlslshaderstring);
1896 Con_Printf("hlsl/default.hlsl written\n");
1899 Con_Printf("failed to write to hlsl/default.hlsl\n");
1902 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
1905 texturemode = GL_MODULATE;
1906 switch (vid.renderpath)
1908 case RENDERPATH_D3D9:
1910 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))));
1911 R_Mesh_TexBind(GL20TU_FIRST , first );
1912 R_Mesh_TexBind(GL20TU_SECOND, second);
1915 case RENDERPATH_D3D10:
1916 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1918 case RENDERPATH_D3D11:
1919 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1921 case RENDERPATH_GL20:
1922 case RENDERPATH_GLES2:
1923 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))));
1924 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1925 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1927 case RENDERPATH_GL13:
1928 case RENDERPATH_GLES1:
1929 R_Mesh_TexBind(0, first );
1930 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1931 R_Mesh_TexBind(1, second);
1933 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1935 case RENDERPATH_GL11:
1936 R_Mesh_TexBind(0, first );
1938 case RENDERPATH_SOFT:
1939 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))));
1940 R_Mesh_TexBind(GL20TU_FIRST , first );
1941 R_Mesh_TexBind(GL20TU_SECOND, second);
1946 void R_SetupShader_DepthOrShadow(void)
1948 switch (vid.renderpath)
1950 case RENDERPATH_D3D9:
1952 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1955 case RENDERPATH_D3D10:
1956 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1958 case RENDERPATH_D3D11:
1959 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1961 case RENDERPATH_GL20:
1962 case RENDERPATH_GLES2:
1963 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1965 case RENDERPATH_GL13:
1966 case RENDERPATH_GLES1:
1967 R_Mesh_TexBind(0, 0);
1968 R_Mesh_TexBind(1, 0);
1970 case RENDERPATH_GL11:
1971 R_Mesh_TexBind(0, 0);
1973 case RENDERPATH_SOFT:
1974 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
1979 void R_SetupShader_ShowDepth(void)
1981 switch (vid.renderpath)
1983 case RENDERPATH_D3D9:
1985 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
1988 case RENDERPATH_D3D10:
1989 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1991 case RENDERPATH_D3D11:
1992 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1994 case RENDERPATH_GL20:
1995 case RENDERPATH_GLES2:
1996 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
1998 case RENDERPATH_GL13:
1999 case RENDERPATH_GLES1:
2001 case RENDERPATH_GL11:
2003 case RENDERPATH_SOFT:
2004 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
2009 extern qboolean r_shadow_usingdeferredprepass;
2010 extern cvar_t r_shadow_deferred_8bitrange;
2011 extern rtexture_t *r_shadow_attenuationgradienttexture;
2012 extern rtexture_t *r_shadow_attenuation2dtexture;
2013 extern rtexture_t *r_shadow_attenuation3dtexture;
2014 extern qboolean r_shadow_usingshadowmap2d;
2015 extern qboolean r_shadow_usingshadowmaportho;
2016 extern float r_shadow_shadowmap_texturescale[2];
2017 extern float r_shadow_shadowmap_parameters[4];
2018 extern qboolean r_shadow_shadowmapvsdct;
2019 extern qboolean r_shadow_shadowmapsampler;
2020 extern int r_shadow_shadowmappcf;
2021 extern rtexture_t *r_shadow_shadowmap2dtexture;
2022 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2023 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2024 extern matrix4x4_t r_shadow_shadowmapmatrix;
2025 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2026 extern int r_shadow_prepass_width;
2027 extern int r_shadow_prepass_height;
2028 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2029 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2030 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2031 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2032 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2034 #define BLENDFUNC_ALLOWS_COLORMOD 1
2035 #define BLENDFUNC_ALLOWS_FOG 2
2036 #define BLENDFUNC_ALLOWS_FOG_HACK0 4
2037 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2038 #define BLENDFUNC_ALLOWS_ANYFOG (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2039 static int R_BlendFuncFlags(int src, int dst)
2043 // a blendfunc allows colormod if:
2044 // a) it can never keep the destination pixel invariant, or
2045 // b) it can keep the destination pixel invariant, and still can do so if colormodded
2046 // this is to prevent unintended side effects from colormod
2048 // a blendfunc allows fog if:
2049 // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2050 // this is to prevent unintended side effects from fog
2052 // these checks are the output of fogeval.pl
2054 r |= BLENDFUNC_ALLOWS_COLORMOD;
2055 if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2056 if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2057 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2058 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2059 if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2060 if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2061 if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2062 if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2063 if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2064 if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2065 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2066 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2067 if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2068 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2069 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2070 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2071 if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2072 if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2073 if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2074 if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2075 if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2080 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)
2082 // select a permutation of the lighting shader appropriate to this
2083 // combination of texture, entity, light source, and fogging, only use the
2084 // minimum features necessary to avoid wasting rendering time in the
2085 // fragment shader on features that are not being used
2086 unsigned int permutation = 0;
2087 unsigned int mode = 0;
2089 static float dummy_colormod[3] = {1, 1, 1};
2090 float *colormod = rsurface.colormod;
2092 matrix4x4_t tempmatrix;
2093 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2094 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2095 permutation |= SHADERPERMUTATION_ALPHAKILL;
2096 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2097 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2098 if (rsurfacepass == RSURFPASS_BACKGROUND)
2100 // distorted background
2101 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2103 mode = SHADERMODE_WATER;
2104 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2106 // this is the right thing to do for wateralpha
2107 GL_BlendFunc(GL_ONE, GL_ZERO);
2108 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2112 // this is the right thing to do for entity alpha
2113 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2114 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2117 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2119 mode = SHADERMODE_REFRACTION;
2120 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2121 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2125 mode = SHADERMODE_GENERIC;
2126 permutation |= SHADERPERMUTATION_DIFFUSE;
2127 GL_BlendFunc(GL_ONE, GL_ZERO);
2128 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2131 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2133 if (r_glsl_offsetmapping.integer)
2135 switch(rsurface.texture->offsetmapping)
2137 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2138 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2139 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2140 case OFFSETMAPPING_OFF: break;
2143 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2144 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2145 // normalmap (deferred prepass), may use alpha test on diffuse
2146 mode = SHADERMODE_DEFERREDGEOMETRY;
2147 GL_BlendFunc(GL_ONE, GL_ZERO);
2148 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2150 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2152 if (r_glsl_offsetmapping.integer)
2154 switch(rsurface.texture->offsetmapping)
2156 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2157 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2158 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2159 case OFFSETMAPPING_OFF: break;
2162 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2163 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2165 mode = SHADERMODE_LIGHTSOURCE;
2166 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2167 permutation |= SHADERPERMUTATION_CUBEFILTER;
2168 if (diffusescale > 0)
2169 permutation |= SHADERPERMUTATION_DIFFUSE;
2170 if (specularscale > 0)
2171 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2172 if (r_refdef.fogenabled)
2173 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2174 if (rsurface.texture->colormapping)
2175 permutation |= SHADERPERMUTATION_COLORMAPPING;
2176 if (r_shadow_usingshadowmap2d)
2178 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2179 if(r_shadow_shadowmapvsdct)
2180 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2182 if (r_shadow_shadowmapsampler)
2183 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2184 if (r_shadow_shadowmappcf > 1)
2185 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2186 else if (r_shadow_shadowmappcf)
2187 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2189 if (rsurface.texture->reflectmasktexture)
2190 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2191 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2192 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2194 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2196 if (r_glsl_offsetmapping.integer)
2198 switch(rsurface.texture->offsetmapping)
2200 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2201 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2202 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2203 case OFFSETMAPPING_OFF: break;
2206 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2207 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2208 // unshaded geometry (fullbright or ambient model lighting)
2209 mode = SHADERMODE_FLATCOLOR;
2210 ambientscale = diffusescale = specularscale = 0;
2211 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2212 permutation |= SHADERPERMUTATION_GLOW;
2213 if (r_refdef.fogenabled)
2214 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2215 if (rsurface.texture->colormapping)
2216 permutation |= SHADERPERMUTATION_COLORMAPPING;
2217 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2219 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2220 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2222 if (r_shadow_shadowmapsampler)
2223 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2224 if (r_shadow_shadowmappcf > 1)
2225 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2226 else if (r_shadow_shadowmappcf)
2227 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2229 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2230 permutation |= SHADERPERMUTATION_REFLECTION;
2231 if (rsurface.texture->reflectmasktexture)
2232 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2233 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2234 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2236 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2238 if (r_glsl_offsetmapping.integer)
2240 switch(rsurface.texture->offsetmapping)
2242 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2243 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2244 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2245 case OFFSETMAPPING_OFF: break;
2248 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2249 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2250 // directional model lighting
2251 mode = SHADERMODE_LIGHTDIRECTION;
2252 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2253 permutation |= SHADERPERMUTATION_GLOW;
2254 permutation |= SHADERPERMUTATION_DIFFUSE;
2255 if (specularscale > 0)
2256 permutation |= SHADERPERMUTATION_SPECULAR;
2257 if (r_refdef.fogenabled)
2258 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2259 if (rsurface.texture->colormapping)
2260 permutation |= SHADERPERMUTATION_COLORMAPPING;
2261 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2263 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2264 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2266 if (r_shadow_shadowmapsampler)
2267 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2268 if (r_shadow_shadowmappcf > 1)
2269 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2270 else if (r_shadow_shadowmappcf)
2271 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2273 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2274 permutation |= SHADERPERMUTATION_REFLECTION;
2275 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2276 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2277 if (rsurface.texture->reflectmasktexture)
2278 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2279 if (r_shadow_bouncegridtexture)
2281 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2282 if (r_shadow_bouncegriddirectional)
2283 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2285 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2286 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2288 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2290 if (r_glsl_offsetmapping.integer)
2292 switch(rsurface.texture->offsetmapping)
2294 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2295 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2296 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2297 case OFFSETMAPPING_OFF: break;
2300 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2301 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2302 // ambient model lighting
2303 mode = SHADERMODE_LIGHTDIRECTION;
2304 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2305 permutation |= SHADERPERMUTATION_GLOW;
2306 if (r_refdef.fogenabled)
2307 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2308 if (rsurface.texture->colormapping)
2309 permutation |= SHADERPERMUTATION_COLORMAPPING;
2310 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2312 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2313 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2315 if (r_shadow_shadowmapsampler)
2316 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2317 if (r_shadow_shadowmappcf > 1)
2318 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2319 else if (r_shadow_shadowmappcf)
2320 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2322 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2323 permutation |= SHADERPERMUTATION_REFLECTION;
2324 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2325 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2326 if (rsurface.texture->reflectmasktexture)
2327 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2328 if (r_shadow_bouncegridtexture)
2330 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2331 if (r_shadow_bouncegriddirectional)
2332 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2334 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2335 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2339 if (r_glsl_offsetmapping.integer)
2341 switch(rsurface.texture->offsetmapping)
2343 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2344 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2345 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2346 case OFFSETMAPPING_OFF: break;
2349 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2350 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2352 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2353 permutation |= SHADERPERMUTATION_GLOW;
2354 if (r_refdef.fogenabled)
2355 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2356 if (rsurface.texture->colormapping)
2357 permutation |= SHADERPERMUTATION_COLORMAPPING;
2358 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2360 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2361 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2363 if (r_shadow_shadowmapsampler)
2364 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2365 if (r_shadow_shadowmappcf > 1)
2366 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2367 else if (r_shadow_shadowmappcf)
2368 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2370 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2371 permutation |= SHADERPERMUTATION_REFLECTION;
2372 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2373 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2374 if (rsurface.texture->reflectmasktexture)
2375 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2376 if (FAKELIGHT_ENABLED)
2378 // fake lightmapping (q1bsp, q3bsp, fullbright map)
2379 mode = SHADERMODE_FAKELIGHT;
2380 permutation |= SHADERPERMUTATION_DIFFUSE;
2381 if (specularscale > 0)
2382 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2384 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2386 // deluxemapping (light direction texture)
2387 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2388 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2390 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2391 permutation |= SHADERPERMUTATION_DIFFUSE;
2392 if (specularscale > 0)
2393 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2395 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2397 // fake deluxemapping (uniform light direction in tangentspace)
2398 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2399 permutation |= SHADERPERMUTATION_DIFFUSE;
2400 if (specularscale > 0)
2401 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2403 else if (rsurface.uselightmaptexture)
2405 // ordinary lightmapping (q1bsp, q3bsp)
2406 mode = SHADERMODE_LIGHTMAP;
2410 // ordinary vertex coloring (q3bsp)
2411 mode = SHADERMODE_VERTEXCOLOR;
2413 if (r_shadow_bouncegridtexture)
2415 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2416 if (r_shadow_bouncegriddirectional)
2417 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2419 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2420 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2422 if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2423 colormod = dummy_colormod;
2424 if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2425 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2426 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2427 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2428 switch(vid.renderpath)
2430 case RENDERPATH_D3D9:
2432 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);
2433 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2434 R_SetupShader_SetPermutationHLSL(mode, permutation);
2435 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2436 if (mode == SHADERMODE_LIGHTSOURCE)
2438 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2439 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2443 if (mode == SHADERMODE_LIGHTDIRECTION)
2445 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2448 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2449 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2450 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2451 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2452 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2454 if (mode == SHADERMODE_LIGHTSOURCE)
2456 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2457 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2458 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2459 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2460 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2462 // additive passes are only darkened by fog, not tinted
2463 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2464 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2468 if (mode == SHADERMODE_FLATCOLOR)
2470 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2472 else if (mode == SHADERMODE_LIGHTDIRECTION)
2474 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]);
2475 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2476 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);
2477 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);
2478 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2479 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2480 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2484 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2485 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2486 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);
2487 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);
2488 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2490 // additive passes are only darkened by fog, not tinted
2491 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2492 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2494 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2495 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);
2496 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2497 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2498 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2499 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2500 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2501 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2502 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2503 if (mode == SHADERMODE_WATER)
2504 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2506 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2507 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2508 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2509 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));
2510 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2511 if (rsurface.texture->pantstexture)
2512 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2514 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2515 if (rsurface.texture->shirttexture)
2516 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2518 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2519 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2520 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2521 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2522 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2523 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2524 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2525 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2526 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2527 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2529 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2530 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2532 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2533 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2534 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2535 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2536 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2537 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2538 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2539 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2540 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2541 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2542 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2543 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2544 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2545 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2546 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2547 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2548 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2549 if (rsurfacepass == RSURFPASS_BACKGROUND)
2551 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2552 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2553 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2557 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2559 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2560 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2561 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2562 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2563 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2565 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2566 if (rsurface.rtlight)
2568 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2569 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2574 case RENDERPATH_D3D10:
2575 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2577 case RENDERPATH_D3D11:
2578 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2580 case RENDERPATH_GL20:
2581 case RENDERPATH_GLES2:
2582 if (!vid.useinterleavedarrays)
2584 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);
2585 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2586 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2587 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2588 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2589 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2590 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2591 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2595 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);
2596 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2598 R_SetupShader_SetPermutationGLSL(mode, permutation);
2599 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2600 if (mode == SHADERMODE_LIGHTSOURCE)
2602 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2603 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2604 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2605 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2606 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2607 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);
2609 // additive passes are only darkened by fog, not tinted
2610 if (r_glsl_permutation->loc_FogColor >= 0)
2611 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2612 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2616 if (mode == SHADERMODE_FLATCOLOR)
2618 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2620 else if (mode == SHADERMODE_LIGHTDIRECTION)
2622 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]);
2623 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]);
2624 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);
2625 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);
2626 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);
2627 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]);
2628 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]);
2632 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]);
2633 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]);
2634 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);
2635 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);
2636 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);
2638 // additive passes are only darkened by fog, not tinted
2639 if (r_glsl_permutation->loc_FogColor >= 0)
2641 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2642 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2644 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2646 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);
2647 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]);
2648 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]);
2649 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]);
2650 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]);
2651 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2652 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2653 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2654 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]);
2656 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2657 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2658 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2659 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]);
2660 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]);
2662 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2663 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));
2664 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2665 if (r_glsl_permutation->loc_Color_Pants >= 0)
2667 if (rsurface.texture->pantstexture)
2668 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2670 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2672 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2674 if (rsurface.texture->shirttexture)
2675 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2677 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2679 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]);
2680 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2681 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2682 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2683 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2684 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2685 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2686 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2687 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2689 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]);
2690 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2691 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);}
2692 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2694 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
2695 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
2696 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
2697 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
2698 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
2699 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
2700 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
2701 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
2702 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
2703 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
2704 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
2705 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
2706 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
2707 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
2708 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);
2709 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
2710 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
2711 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2712 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2713 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2714 if (rsurfacepass == RSURFPASS_BACKGROUND)
2716 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);
2717 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);
2718 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);
2722 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);
2724 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2725 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2726 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
2727 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
2728 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2730 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture );
2731 if (rsurface.rtlight)
2733 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2734 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2737 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2740 case RENDERPATH_GL11:
2741 case RENDERPATH_GL13:
2742 case RENDERPATH_GLES1:
2744 case RENDERPATH_SOFT:
2745 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);
2746 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2747 R_SetupShader_SetPermutationSoft(mode, permutation);
2748 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2749 if (mode == SHADERMODE_LIGHTSOURCE)
2751 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2752 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2753 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2754 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2755 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2756 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2758 // additive passes are only darkened by fog, not tinted
2759 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2760 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2764 if (mode == SHADERMODE_FLATCOLOR)
2766 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2768 else if (mode == SHADERMODE_LIGHTDIRECTION)
2770 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]);
2771 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2772 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);
2773 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);
2774 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2775 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]);
2776 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2780 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2781 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2782 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);
2783 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);
2784 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2786 // additive passes are only darkened by fog, not tinted
2787 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2788 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2790 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2791 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);
2792 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2793 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2794 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]);
2795 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]);
2796 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2797 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2798 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2799 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2801 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2802 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2803 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2804 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2805 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]);
2807 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2808 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));
2809 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2810 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2812 if (rsurface.texture->pantstexture)
2813 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2815 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2817 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2819 if (rsurface.texture->shirttexture)
2820 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2822 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2824 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2825 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2826 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2827 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2828 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2829 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2830 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2831 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2832 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2834 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2835 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2837 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2838 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2839 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2840 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2841 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2842 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2843 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2844 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2845 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2846 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2847 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2848 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2849 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2850 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2851 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2852 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2853 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2854 if (rsurfacepass == RSURFPASS_BACKGROUND)
2856 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2857 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2858 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2862 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2864 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2865 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2866 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2867 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2868 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2870 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2871 if (rsurface.rtlight)
2873 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2874 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2881 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2883 // select a permutation of the lighting shader appropriate to this
2884 // combination of texture, entity, light source, and fogging, only use the
2885 // minimum features necessary to avoid wasting rendering time in the
2886 // fragment shader on features that are not being used
2887 unsigned int permutation = 0;
2888 unsigned int mode = 0;
2889 const float *lightcolorbase = rtlight->currentcolor;
2890 float ambientscale = rtlight->ambientscale;
2891 float diffusescale = rtlight->diffusescale;
2892 float specularscale = rtlight->specularscale;
2893 // this is the location of the light in view space
2894 vec3_t viewlightorigin;
2895 // this transforms from view space (camera) to light space (cubemap)
2896 matrix4x4_t viewtolight;
2897 matrix4x4_t lighttoview;
2898 float viewtolight16f[16];
2899 float range = 1.0f / r_shadow_deferred_8bitrange.value;
2901 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2902 if (rtlight->currentcubemap != r_texture_whitecube)
2903 permutation |= SHADERPERMUTATION_CUBEFILTER;
2904 if (diffusescale > 0)
2905 permutation |= SHADERPERMUTATION_DIFFUSE;
2906 if (specularscale > 0 && r_shadow_gloss.integer > 0)
2907 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2908 if (r_shadow_usingshadowmap2d)
2910 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2911 if (r_shadow_shadowmapvsdct)
2912 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2914 if (r_shadow_shadowmapsampler)
2915 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2916 if (r_shadow_shadowmappcf > 1)
2917 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2918 else if (r_shadow_shadowmappcf)
2919 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2921 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2922 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2923 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2924 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2925 switch(vid.renderpath)
2927 case RENDERPATH_D3D9:
2929 R_SetupShader_SetPermutationHLSL(mode, permutation);
2930 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2931 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
2932 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2933 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2934 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2935 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2936 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2937 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2938 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2939 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2941 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2942 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthcolortexture );
2943 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2944 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2945 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dcolortexture );
2946 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2949 case RENDERPATH_D3D10:
2950 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2952 case RENDERPATH_D3D11:
2953 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2955 case RENDERPATH_GL20:
2956 case RENDERPATH_GLES2:
2957 R_SetupShader_SetPermutationGLSL(mode, permutation);
2958 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2959 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
2960 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);
2961 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);
2962 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);
2963 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]);
2964 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]);
2965 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));
2966 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]);
2967 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
2969 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2970 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2971 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2972 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2973 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );
2974 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2976 case RENDERPATH_GL11:
2977 case RENDERPATH_GL13:
2978 case RENDERPATH_GLES1:
2980 case RENDERPATH_SOFT:
2981 R_SetupShader_SetPermutationGLSL(mode, permutation);
2982 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2983 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
2984 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2985 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2986 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2987 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2988 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]);
2989 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));
2990 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2991 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2993 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2994 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2995 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2996 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2997 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
2998 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3003 #define SKINFRAME_HASH 1024
3007 int loadsequence; // incremented each level change
3008 memexpandablearray_t array;
3009 skinframe_t *hash[SKINFRAME_HASH];
3012 r_skinframe_t r_skinframe;
3014 void R_SkinFrame_PrepareForPurge(void)
3016 r_skinframe.loadsequence++;
3017 // wrap it without hitting zero
3018 if (r_skinframe.loadsequence >= 200)
3019 r_skinframe.loadsequence = 1;
3022 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3026 // mark the skinframe as used for the purging code
3027 skinframe->loadsequence = r_skinframe.loadsequence;
3030 void R_SkinFrame_Purge(void)
3034 for (i = 0;i < SKINFRAME_HASH;i++)
3036 for (s = r_skinframe.hash[i];s;s = s->next)
3038 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3040 if (s->merged == s->base)
3042 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3043 R_PurgeTexture(s->stain );s->stain = NULL;
3044 R_PurgeTexture(s->merged);s->merged = NULL;
3045 R_PurgeTexture(s->base );s->base = NULL;
3046 R_PurgeTexture(s->pants );s->pants = NULL;
3047 R_PurgeTexture(s->shirt );s->shirt = NULL;
3048 R_PurgeTexture(s->nmap );s->nmap = NULL;
3049 R_PurgeTexture(s->gloss );s->gloss = NULL;
3050 R_PurgeTexture(s->glow );s->glow = NULL;
3051 R_PurgeTexture(s->fog );s->fog = NULL;
3052 R_PurgeTexture(s->reflect);s->reflect = NULL;
3053 s->loadsequence = 0;
3059 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3061 char basename[MAX_QPATH];
3063 Image_StripImageExtension(name, basename, sizeof(basename));
3065 if( last == NULL ) {
3067 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3068 item = r_skinframe.hash[hashindex];
3073 // linearly search through the hash bucket
3074 for( ; item ; item = item->next ) {
3075 if( !strcmp( item->basename, basename ) ) {
3082 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3086 char basename[MAX_QPATH];
3088 Image_StripImageExtension(name, basename, sizeof(basename));
3090 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3091 for (item = r_skinframe.hash[hashindex];item;item = item->next)
3092 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3096 rtexture_t *dyntexture;
3097 // check whether its a dynamic texture
3098 dyntexture = CL_GetDynTexture( basename );
3099 if (!add && !dyntexture)
3101 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3102 memset(item, 0, sizeof(*item));
3103 strlcpy(item->basename, basename, sizeof(item->basename));
3104 item->base = dyntexture; // either NULL or dyntexture handle
3105 item->textureflags = textureflags;
3106 item->comparewidth = comparewidth;
3107 item->compareheight = compareheight;
3108 item->comparecrc = comparecrc;
3109 item->next = r_skinframe.hash[hashindex];
3110 r_skinframe.hash[hashindex] = item;
3112 else if( item->base == NULL )
3114 rtexture_t *dyntexture;
3115 // check whether its a dynamic texture
3116 // 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]
3117 dyntexture = CL_GetDynTexture( basename );
3118 item->base = dyntexture; // either NULL or dyntexture handle
3121 R_SkinFrame_MarkUsed(item);
3125 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3127 unsigned long long avgcolor[5], wsum; \
3135 for(pix = 0; pix < cnt; ++pix) \
3138 for(comp = 0; comp < 3; ++comp) \
3140 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3143 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3145 for(comp = 0; comp < 3; ++comp) \
3146 avgcolor[comp] += getpixel * w; \
3149 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3150 avgcolor[4] += getpixel; \
3152 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3154 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3155 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3156 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3157 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3160 extern cvar_t gl_picmip;
3161 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3164 unsigned char *pixels;
3165 unsigned char *bumppixels;
3166 unsigned char *basepixels = NULL;
3167 int basepixels_width = 0;
3168 int basepixels_height = 0;
3169 skinframe_t *skinframe;
3170 rtexture_t *ddsbase = NULL;
3171 qboolean ddshasalpha = false;
3172 float ddsavgcolor[4];
3173 char basename[MAX_QPATH];
3174 int miplevel = R_PicmipForFlags(textureflags);
3175 int savemiplevel = miplevel;
3178 if (cls.state == ca_dedicated)
3181 // return an existing skinframe if already loaded
3182 // if loading of the first image fails, don't make a new skinframe as it
3183 // would cause all future lookups of this to be missing
3184 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3185 if (skinframe && skinframe->base)
3188 Image_StripImageExtension(name, basename, sizeof(basename));
3190 // check for DDS texture file first
3191 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3193 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3194 if (basepixels == NULL)
3198 // FIXME handle miplevel
3200 if (developer_loading.integer)
3201 Con_Printf("loading skin \"%s\"\n", name);
3203 // we've got some pixels to store, so really allocate this new texture now
3205 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3206 skinframe->stain = NULL;
3207 skinframe->merged = NULL;
3208 skinframe->base = NULL;
3209 skinframe->pants = NULL;
3210 skinframe->shirt = NULL;
3211 skinframe->nmap = NULL;
3212 skinframe->gloss = NULL;
3213 skinframe->glow = NULL;
3214 skinframe->fog = NULL;
3215 skinframe->reflect = NULL;
3216 skinframe->hasalpha = false;
3220 skinframe->base = ddsbase;
3221 skinframe->hasalpha = ddshasalpha;
3222 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3223 if (r_loadfog && skinframe->hasalpha)
3224 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3225 //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]);
3229 basepixels_width = image_width;
3230 basepixels_height = image_height;
3231 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);
3232 if (textureflags & TEXF_ALPHA)
3234 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3236 if (basepixels[j] < 255)
3238 skinframe->hasalpha = true;
3242 if (r_loadfog && skinframe->hasalpha)
3244 // has transparent pixels
3245 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3246 for (j = 0;j < image_width * image_height * 4;j += 4)
3251 pixels[j+3] = basepixels[j+3];
3253 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);
3257 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3258 //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]);
3259 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3260 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3261 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3262 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3267 mymiplevel = savemiplevel;
3268 if (r_loadnormalmap)
3269 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);
3270 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3272 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3273 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3274 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3275 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3278 // _norm is the name used by tenebrae and has been adopted as standard
3279 if (r_loadnormalmap && skinframe->nmap == NULL)
3281 mymiplevel = savemiplevel;
3282 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3284 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);
3288 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3290 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3291 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3292 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);
3294 Mem_Free(bumppixels);
3296 else if (r_shadow_bumpscale_basetexture.value > 0)
3298 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3299 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3300 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);
3303 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3304 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3307 // _luma is supported only for tenebrae compatibility
3308 // _glow is the preferred name
3309 mymiplevel = savemiplevel;
3310 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))))
3312 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);
3313 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3314 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3315 Mem_Free(pixels);pixels = NULL;
3318 mymiplevel = savemiplevel;
3319 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3321 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);
3322 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3323 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3328 mymiplevel = savemiplevel;
3329 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3331 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);
3332 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3333 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3338 mymiplevel = savemiplevel;
3339 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3341 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);
3342 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3343 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3348 mymiplevel = savemiplevel;
3349 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3351 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);
3352 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3353 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3359 Mem_Free(basepixels);
3364 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3365 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3368 unsigned char *temp1, *temp2;
3369 skinframe_t *skinframe;
3371 if (cls.state == ca_dedicated)
3374 // if already loaded just return it, otherwise make a new skinframe
3375 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3376 if (skinframe && skinframe->base)
3379 skinframe->stain = NULL;
3380 skinframe->merged = NULL;
3381 skinframe->base = NULL;
3382 skinframe->pants = NULL;
3383 skinframe->shirt = NULL;
3384 skinframe->nmap = NULL;
3385 skinframe->gloss = NULL;
3386 skinframe->glow = NULL;
3387 skinframe->fog = NULL;
3388 skinframe->reflect = NULL;
3389 skinframe->hasalpha = false;
3391 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3395 if (developer_loading.integer)
3396 Con_Printf("loading 32bit skin \"%s\"\n", name);
3398 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3400 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3401 temp2 = temp1 + width * height * 4;
3402 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3403 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);
3406 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3407 if (textureflags & TEXF_ALPHA)
3409 for (i = 3;i < width * height * 4;i += 4)
3411 if (skindata[i] < 255)
3413 skinframe->hasalpha = true;
3417 if (r_loadfog && skinframe->hasalpha)
3419 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3420 memcpy(fogpixels, skindata, width * height * 4);
3421 for (i = 0;i < width * height * 4;i += 4)
3422 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3423 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3424 Mem_Free(fogpixels);
3428 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3429 //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]);
3434 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3438 skinframe_t *skinframe;
3440 if (cls.state == ca_dedicated)
3443 // if already loaded just return it, otherwise make a new skinframe
3444 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3445 if (skinframe && skinframe->base)
3448 skinframe->stain = NULL;
3449 skinframe->merged = NULL;
3450 skinframe->base = NULL;
3451 skinframe->pants = NULL;
3452 skinframe->shirt = NULL;
3453 skinframe->nmap = NULL;
3454 skinframe->gloss = NULL;
3455 skinframe->glow = NULL;
3456 skinframe->fog = NULL;
3457 skinframe->reflect = NULL;
3458 skinframe->hasalpha = false;
3460 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3464 if (developer_loading.integer)
3465 Con_Printf("loading quake skin \"%s\"\n", name);
3467 // 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)
3468 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3469 memcpy(skinframe->qpixels, skindata, width*height);
3470 skinframe->qwidth = width;
3471 skinframe->qheight = height;
3474 for (i = 0;i < width * height;i++)
3475 featuresmask |= palette_featureflags[skindata[i]];
3477 skinframe->hasalpha = false;
3478 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3479 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3480 skinframe->qgeneratemerged = true;
3481 skinframe->qgeneratebase = skinframe->qhascolormapping;
3482 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3484 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3485 //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]);
3490 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3494 unsigned char *skindata;
3496 if (!skinframe->qpixels)
3499 if (!skinframe->qhascolormapping)
3500 colormapped = false;
3504 if (!skinframe->qgeneratebase)
3509 if (!skinframe->qgeneratemerged)
3513 width = skinframe->qwidth;
3514 height = skinframe->qheight;
3515 skindata = skinframe->qpixels;
3517 if (skinframe->qgeneratenmap)
3519 unsigned char *temp1, *temp2;
3520 skinframe->qgeneratenmap = false;
3521 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3522 temp2 = temp1 + width * height * 4;
3523 // use either a custom palette or the quake palette
3524 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3525 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3526 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);
3530 if (skinframe->qgenerateglow)
3532 skinframe->qgenerateglow = false;
3533 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
3538 skinframe->qgeneratebase = false;
3539 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);
3540 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);
3541 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);
3545 skinframe->qgeneratemerged = false;
3546 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);
3549 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3551 Mem_Free(skinframe->qpixels);
3552 skinframe->qpixels = NULL;
3556 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)
3559 skinframe_t *skinframe;
3561 if (cls.state == ca_dedicated)
3564 // if already loaded just return it, otherwise make a new skinframe
3565 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3566 if (skinframe && skinframe->base)
3569 skinframe->stain = NULL;
3570 skinframe->merged = NULL;
3571 skinframe->base = NULL;
3572 skinframe->pants = NULL;
3573 skinframe->shirt = NULL;
3574 skinframe->nmap = NULL;
3575 skinframe->gloss = NULL;
3576 skinframe->glow = NULL;
3577 skinframe->fog = NULL;
3578 skinframe->reflect = NULL;
3579 skinframe->hasalpha = false;
3581 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3585 if (developer_loading.integer)
3586 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3588 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3589 if (textureflags & TEXF_ALPHA)
3591 for (i = 0;i < width * height;i++)
3593 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3595 skinframe->hasalpha = true;
3599 if (r_loadfog && skinframe->hasalpha)
3600 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3603 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3604 //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]);
3609 skinframe_t *R_SkinFrame_LoadMissing(void)
3611 skinframe_t *skinframe;
3613 if (cls.state == ca_dedicated)
3616 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3617 skinframe->stain = NULL;
3618 skinframe->merged = NULL;
3619 skinframe->base = NULL;
3620 skinframe->pants = NULL;
3621 skinframe->shirt = NULL;
3622 skinframe->nmap = NULL;
3623 skinframe->gloss = NULL;
3624 skinframe->glow = NULL;
3625 skinframe->fog = NULL;
3626 skinframe->reflect = NULL;
3627 skinframe->hasalpha = false;
3629 skinframe->avgcolor[0] = rand() / RAND_MAX;
3630 skinframe->avgcolor[1] = rand() / RAND_MAX;
3631 skinframe->avgcolor[2] = rand() / RAND_MAX;
3632 skinframe->avgcolor[3] = 1;
3637 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3638 typedef struct suffixinfo_s
3641 qboolean flipx, flipy, flipdiagonal;
3644 static suffixinfo_t suffix[3][6] =
3647 {"px", false, false, false},
3648 {"nx", false, false, false},
3649 {"py", false, false, false},
3650 {"ny", false, false, false},
3651 {"pz", false, false, false},
3652 {"nz", false, false, false}
3655 {"posx", false, false, false},
3656 {"negx", false, false, false},
3657 {"posy", false, false, false},
3658 {"negy", false, false, false},
3659 {"posz", false, false, false},
3660 {"negz", false, false, false}
3663 {"rt", true, false, true},
3664 {"lf", false, true, true},
3665 {"ft", true, true, false},
3666 {"bk", false, false, false},
3667 {"up", true, false, true},
3668 {"dn", true, false, true}
3672 static int componentorder[4] = {0, 1, 2, 3};
3674 rtexture_t *R_LoadCubemap(const char *basename)
3676 int i, j, cubemapsize;
3677 unsigned char *cubemappixels, *image_buffer;
3678 rtexture_t *cubemaptexture;
3680 // must start 0 so the first loadimagepixels has no requested width/height
3682 cubemappixels = NULL;
3683 cubemaptexture = NULL;
3684 // keep trying different suffix groups (posx, px, rt) until one loads
3685 for (j = 0;j < 3 && !cubemappixels;j++)
3687 // load the 6 images in the suffix group
3688 for (i = 0;i < 6;i++)
3690 // generate an image name based on the base and and suffix
3691 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3693 if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3695 // an image loaded, make sure width and height are equal
3696 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3698 // if this is the first image to load successfully, allocate the cubemap memory
3699 if (!cubemappixels && image_width >= 1)
3701 cubemapsize = image_width;
3702 // note this clears to black, so unavailable sides are black
3703 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3705 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3707 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);
3710 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3712 Mem_Free(image_buffer);
3716 // if a cubemap loaded, upload it
3719 if (developer_loading.integer)
3720 Con_Printf("loading cubemap \"%s\"\n", basename);
3722 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);
3723 Mem_Free(cubemappixels);
3727 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3728 if (developer_loading.integer)
3730 Con_Printf("(tried tried images ");
3731 for (j = 0;j < 3;j++)
3732 for (i = 0;i < 6;i++)
3733 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3734 Con_Print(" and was unable to find any of them).\n");
3737 return cubemaptexture;
3740 rtexture_t *R_GetCubemap(const char *basename)
3743 for (i = 0;i < r_texture_numcubemaps;i++)
3744 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
3745 return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
3746 if (i >= MAX_CUBEMAPS)
3747 return r_texture_whitecube;
3748 r_texture_numcubemaps++;
3749 strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
3750 r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
3751 return r_texture_cubemaps[i].texture;
3754 void R_FreeCubemaps(void)
3757 for (i = 0;i < r_texture_numcubemaps;i++)
3759 if (developer_loading.integer)
3760 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
3761 if (r_texture_cubemaps[i].texture)
3762 R_FreeTexture(r_texture_cubemaps[i].texture);
3764 r_texture_numcubemaps = 0;
3767 void R_Main_FreeViewCache(void)
3769 if (r_refdef.viewcache.entityvisible)
3770 Mem_Free(r_refdef.viewcache.entityvisible);
3771 if (r_refdef.viewcache.world_pvsbits)
3772 Mem_Free(r_refdef.viewcache.world_pvsbits);
3773 if (r_refdef.viewcache.world_leafvisible)
3774 Mem_Free(r_refdef.viewcache.world_leafvisible);
3775 if (r_refdef.viewcache.world_surfacevisible)
3776 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3777 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3780 void R_Main_ResizeViewCache(void)
3782 int numentities = r_refdef.scene.numentities;
3783 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3784 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3785 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3786 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3787 if (r_refdef.viewcache.maxentities < numentities)
3789 r_refdef.viewcache.maxentities = numentities;
3790 if (r_refdef.viewcache.entityvisible)
3791 Mem_Free(r_refdef.viewcache.entityvisible);
3792 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3794 if (r_refdef.viewcache.world_numclusters != numclusters)
3796 r_refdef.viewcache.world_numclusters = numclusters;
3797 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3798 if (r_refdef.viewcache.world_pvsbits)
3799 Mem_Free(r_refdef.viewcache.world_pvsbits);
3800 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3802 if (r_refdef.viewcache.world_numleafs != numleafs)
3804 r_refdef.viewcache.world_numleafs = numleafs;
3805 if (r_refdef.viewcache.world_leafvisible)
3806 Mem_Free(r_refdef.viewcache.world_leafvisible);
3807 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3809 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3811 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3812 if (r_refdef.viewcache.world_surfacevisible)
3813 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3814 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3818 extern rtexture_t *loadingscreentexture;
3819 void gl_main_start(void)
3821 loadingscreentexture = NULL;
3822 r_texture_blanknormalmap = NULL;
3823 r_texture_white = NULL;
3824 r_texture_grey128 = NULL;
3825 r_texture_black = NULL;
3826 r_texture_whitecube = NULL;
3827 r_texture_normalizationcube = NULL;
3828 r_texture_fogattenuation = NULL;
3829 r_texture_fogheighttexture = NULL;
3830 r_texture_gammaramps = NULL;
3831 r_texture_numcubemaps = 0;
3833 r_loaddds = r_texture_dds_load.integer != 0;
3834 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3836 switch(vid.renderpath)
3838 case RENDERPATH_GL20:
3839 case RENDERPATH_D3D9:
3840 case RENDERPATH_D3D10:
3841 case RENDERPATH_D3D11:
3842 case RENDERPATH_SOFT:
3843 case RENDERPATH_GLES2:
3844 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3845 Cvar_SetValueQuick(&gl_combine, 1);
3846 Cvar_SetValueQuick(&r_glsl, 1);
3847 r_loadnormalmap = true;
3851 case RENDERPATH_GL13:
3852 case RENDERPATH_GLES1:
3853 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3854 Cvar_SetValueQuick(&gl_combine, 1);
3855 Cvar_SetValueQuick(&r_glsl, 0);
3856 r_loadnormalmap = false;
3857 r_loadgloss = false;
3860 case RENDERPATH_GL11:
3861 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3862 Cvar_SetValueQuick(&gl_combine, 0);
3863 Cvar_SetValueQuick(&r_glsl, 0);
3864 r_loadnormalmap = false;
3865 r_loadgloss = false;
3871 R_FrameData_Reset();
3875 memset(r_queries, 0, sizeof(r_queries));
3877 r_qwskincache = NULL;
3878 r_qwskincache_size = 0;
3880 // due to caching of texture_t references, the collision cache must be reset
3881 Collision_Cache_Reset(true);
3883 // set up r_skinframe loading system for textures
3884 memset(&r_skinframe, 0, sizeof(r_skinframe));
3885 r_skinframe.loadsequence = 1;
3886 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3888 r_main_texturepool = R_AllocTexturePool();
3889 R_BuildBlankTextures();
3891 if (vid.support.arb_texture_cube_map)
3894 R_BuildNormalizationCube();
3896 r_texture_fogattenuation = NULL;
3897 r_texture_fogheighttexture = NULL;
3898 r_texture_gammaramps = NULL;
3899 //r_texture_fogintensity = NULL;
3900 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3901 memset(&r_waterstate, 0, sizeof(r_waterstate));
3902 r_glsl_permutation = NULL;
3903 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3904 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3905 glslshaderstring = NULL;
3907 r_hlsl_permutation = NULL;
3908 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3909 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
3911 hlslshaderstring = NULL;
3912 memset(&r_svbsp, 0, sizeof (r_svbsp));
3914 r_refdef.fogmasktable_density = 0;
3917 void gl_main_shutdown(void)
3920 R_FrameData_Reset();
3922 R_Main_FreeViewCache();
3924 switch(vid.renderpath)
3926 case RENDERPATH_GL11:
3927 case RENDERPATH_GL13:
3928 case RENDERPATH_GL20:
3929 case RENDERPATH_GLES1:
3930 case RENDERPATH_GLES2:
3932 qglDeleteQueriesARB(r_maxqueries, r_queries);
3934 case RENDERPATH_D3D9:
3935 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3937 case RENDERPATH_D3D10:
3938 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3940 case RENDERPATH_D3D11:
3941 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3943 case RENDERPATH_SOFT:
3949 memset(r_queries, 0, sizeof(r_queries));
3951 r_qwskincache = NULL;
3952 r_qwskincache_size = 0;
3954 // clear out the r_skinframe state
3955 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3956 memset(&r_skinframe, 0, sizeof(r_skinframe));
3959 Mem_Free(r_svbsp.nodes);
3960 memset(&r_svbsp, 0, sizeof (r_svbsp));
3961 R_FreeTexturePool(&r_main_texturepool);
3962 loadingscreentexture = NULL;
3963 r_texture_blanknormalmap = NULL;
3964 r_texture_white = NULL;
3965 r_texture_grey128 = NULL;
3966 r_texture_black = NULL;
3967 r_texture_whitecube = NULL;
3968 r_texture_normalizationcube = NULL;
3969 r_texture_fogattenuation = NULL;
3970 r_texture_fogheighttexture = NULL;
3971 r_texture_gammaramps = NULL;
3972 r_texture_numcubemaps = 0;
3973 //r_texture_fogintensity = NULL;
3974 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3975 memset(&r_waterstate, 0, sizeof(r_waterstate));
3978 r_glsl_permutation = NULL;
3979 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3980 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
3981 glslshaderstring = NULL;
3983 r_hlsl_permutation = NULL;
3984 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3985 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
3987 hlslshaderstring = NULL;
3990 extern void CL_ParseEntityLump(char *entitystring);
3991 void gl_main_newmap(void)
3993 // FIXME: move this code to client
3994 char *entities, entname[MAX_QPATH];
3996 Mem_Free(r_qwskincache);
3997 r_qwskincache = NULL;
3998 r_qwskincache_size = 0;
4001 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4002 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4004 CL_ParseEntityLump(entities);
4008 if (cl.worldmodel->brush.entities)
4009 CL_ParseEntityLump(cl.worldmodel->brush.entities);
4011 R_Main_FreeViewCache();
4013 R_FrameData_Reset();
4016 void GL_Main_Init(void)
4018 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4020 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4021 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4022 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4023 if (gamemode == GAME_NEHAHRA)
4025 Cvar_RegisterVariable (&gl_fogenable);
4026 Cvar_RegisterVariable (&gl_fogdensity);
4027 Cvar_RegisterVariable (&gl_fogred);
4028 Cvar_RegisterVariable (&gl_foggreen);
4029 Cvar_RegisterVariable (&gl_fogblue);
4030 Cvar_RegisterVariable (&gl_fogstart);
4031 Cvar_RegisterVariable (&gl_fogend);
4032 Cvar_RegisterVariable (&gl_skyclip);
4034 Cvar_RegisterVariable(&r_motionblur);
4035 Cvar_RegisterVariable(&r_motionblur_maxblur);
4036 Cvar_RegisterVariable(&r_motionblur_bmin);
4037 Cvar_RegisterVariable(&r_motionblur_vmin);
4038 Cvar_RegisterVariable(&r_motionblur_vmax);
4039 Cvar_RegisterVariable(&r_motionblur_vcoeff);
4040 Cvar_RegisterVariable(&r_motionblur_randomize);
4041 Cvar_RegisterVariable(&r_damageblur);
4042 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4043 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4044 Cvar_RegisterVariable(&r_equalize_entities_by);
4045 Cvar_RegisterVariable(&r_equalize_entities_to);
4046 Cvar_RegisterVariable(&r_depthfirst);
4047 Cvar_RegisterVariable(&r_useinfinitefarclip);
4048 Cvar_RegisterVariable(&r_farclip_base);
4049 Cvar_RegisterVariable(&r_farclip_world);
4050 Cvar_RegisterVariable(&r_nearclip);
4051 Cvar_RegisterVariable(&r_deformvertexes);
4052 Cvar_RegisterVariable(&r_transparent);
4053 Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4054 Cvar_RegisterVariable(&r_showoverdraw);
4055 Cvar_RegisterVariable(&r_showbboxes);
4056 Cvar_RegisterVariable(&r_showsurfaces);
4057 Cvar_RegisterVariable(&r_showtris);
4058 Cvar_RegisterVariable(&r_shownormals);
4059 Cvar_RegisterVariable(&r_showlighting);
4060 Cvar_RegisterVariable(&r_showshadowvolumes);
4061 Cvar_RegisterVariable(&r_showcollisionbrushes);
4062 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4063 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4064 Cvar_RegisterVariable(&r_showdisabledepthtest);
4065 Cvar_RegisterVariable(&r_drawportals);
4066 Cvar_RegisterVariable(&r_drawentities);
4067 Cvar_RegisterVariable(&r_draw2d);
4068 Cvar_RegisterVariable(&r_drawworld);
4069 Cvar_RegisterVariable(&r_cullentities_trace);
4070 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4071 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4072 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4073 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4074 Cvar_RegisterVariable(&r_drawviewmodel);
4075 Cvar_RegisterVariable(&r_drawexteriormodel);
4076 Cvar_RegisterVariable(&r_speeds);
4077 Cvar_RegisterVariable(&r_fullbrights);
4078 Cvar_RegisterVariable(&r_wateralpha);
4079 Cvar_RegisterVariable(&r_dynamic);
4080 Cvar_RegisterVariable(&r_fakelight);
4081 Cvar_RegisterVariable(&r_fakelight_intensity);
4082 Cvar_RegisterVariable(&r_fullbright);
4083 Cvar_RegisterVariable(&r_shadows);
4084 Cvar_RegisterVariable(&r_shadows_darken);
4085 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4086 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4087 Cvar_RegisterVariable(&r_shadows_throwdistance);
4088 Cvar_RegisterVariable(&r_shadows_throwdirection);
4089 Cvar_RegisterVariable(&r_shadows_focus);
4090 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4091 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4092 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4093 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4094 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4095 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4096 Cvar_RegisterVariable(&r_fog_exp2);
4097 Cvar_RegisterVariable(&r_fog_clear);
4098 Cvar_RegisterVariable(&r_drawfog);
4099 Cvar_RegisterVariable(&r_transparentdepthmasking);
4100 Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4101 Cvar_RegisterVariable(&r_transparent_sortarraysize);
4102 Cvar_RegisterVariable(&r_texture_dds_load);
4103 Cvar_RegisterVariable(&r_texture_dds_save);
4104 Cvar_RegisterVariable(&r_textureunits);
4105 Cvar_RegisterVariable(&gl_combine);
4106 Cvar_RegisterVariable(&r_viewfbo);
4107 Cvar_RegisterVariable(&r_viewscale);
4108 Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4109 Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4110 Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4111 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4112 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4113 Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4114 Cvar_RegisterVariable(&r_glsl);
4115 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4116 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4117 Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4118 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4119 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4120 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4121 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4122 Cvar_RegisterVariable(&r_glsl_postprocess);
4123 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4124 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4125 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4126 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4127 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4128 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4129 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4130 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4132 Cvar_RegisterVariable(&r_water);
4133 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4134 Cvar_RegisterVariable(&r_water_clippingplanebias);
4135 Cvar_RegisterVariable(&r_water_refractdistort);
4136 Cvar_RegisterVariable(&r_water_reflectdistort);
4137 Cvar_RegisterVariable(&r_water_scissormode);
4138 Cvar_RegisterVariable(&r_lerpsprites);
4139 Cvar_RegisterVariable(&r_lerpmodels);
4140 Cvar_RegisterVariable(&r_lerplightstyles);
4141 Cvar_RegisterVariable(&r_waterscroll);
4142 Cvar_RegisterVariable(&r_bloom);
4143 Cvar_RegisterVariable(&r_bloom_colorscale);
4144 Cvar_RegisterVariable(&r_bloom_brighten);
4145 Cvar_RegisterVariable(&r_bloom_blur);
4146 Cvar_RegisterVariable(&r_bloom_resolution);
4147 Cvar_RegisterVariable(&r_bloom_colorexponent);
4148 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4149 Cvar_RegisterVariable(&r_hdr);
4150 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4151 Cvar_RegisterVariable(&r_hdr_glowintensity);
4152 Cvar_RegisterVariable(&r_hdr_range);
4153 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4154 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4155 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4156 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4157 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4158 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4159 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4160 Cvar_RegisterVariable(&developer_texturelogging);
4161 Cvar_RegisterVariable(&gl_lightmaps);
4162 Cvar_RegisterVariable(&r_test);
4163 Cvar_RegisterVariable(&r_glsl_saturation);
4164 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4165 Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4166 Cvar_RegisterVariable(&r_framedatasize);
4167 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4168 Cvar_SetValue("r_fullbrights", 0);
4169 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4171 Cvar_RegisterVariable(&r_track_sprites);
4172 Cvar_RegisterVariable(&r_track_sprites_flags);
4173 Cvar_RegisterVariable(&r_track_sprites_scalew);
4174 Cvar_RegisterVariable(&r_track_sprites_scaleh);
4175 Cvar_RegisterVariable(&r_overheadsprites_perspective);
4176 Cvar_RegisterVariable(&r_overheadsprites_pushback);
4177 Cvar_RegisterVariable(&r_overheadsprites_scalex);
4178 Cvar_RegisterVariable(&r_overheadsprites_scaley);
4181 extern void R_Textures_Init(void);
4182 extern void GL_Draw_Init(void);
4183 extern void GL_Main_Init(void);
4184 extern void R_Shadow_Init(void);
4185 extern void R_Sky_Init(void);
4186 extern void GL_Surf_Init(void);
4187 extern void R_Particles_Init(void);
4188 extern void R_Explosion_Init(void);
4189 extern void gl_backend_init(void);
4190 extern void Sbar_Init(void);
4191 extern void R_LightningBeams_Init(void);
4192 extern void Mod_RenderInit(void);
4193 extern void Font_Init(void);
4195 void Render_Init(void)
4208 R_LightningBeams_Init();
4217 extern char *ENGINE_EXTENSIONS;
4220 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4221 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4222 gl_version = (const char *)qglGetString(GL_VERSION);
4223 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4227 if (!gl_platformextensions)
4228 gl_platformextensions = "";
4230 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4231 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4232 Con_Printf("GL_VERSION: %s\n", gl_version);
4233 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4234 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4236 VID_CheckExtensions();
4238 // LordHavoc: report supported extensions
4239 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4241 // clear to black (loading plaque will be seen over this)
4242 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4245 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4249 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4251 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4254 p = r_refdef.view.frustum + i;
4259 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4263 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4267 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4271 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4275 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4279 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4283 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4287 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4295 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4299 for (i = 0;i < numplanes;i++)
4306 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4310 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4314 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4318 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4322 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4326 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4330 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4334 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4342 //==================================================================================
4344 // LordHavoc: this stores temporary data used within the same frame
4346 typedef struct r_framedata_mem_s
4348 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4349 size_t size; // how much usable space
4350 size_t current; // how much space in use
4351 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4352 size_t wantedsize; // how much space was allocated
4353 unsigned char *data; // start of real data (16byte aligned)
4357 static r_framedata_mem_t *r_framedata_mem;
4359 void R_FrameData_Reset(void)
4361 while (r_framedata_mem)
4363 r_framedata_mem_t *next = r_framedata_mem->purge;
4364 Mem_Free(r_framedata_mem);
4365 r_framedata_mem = next;
4369 void R_FrameData_Resize(void)
4372 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4373 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4374 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4376 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4377 newmem->wantedsize = wantedsize;
4378 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4379 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4380 newmem->current = 0;
4382 newmem->purge = r_framedata_mem;
4383 r_framedata_mem = newmem;
4387 void R_FrameData_NewFrame(void)
4389 R_FrameData_Resize();
4390 if (!r_framedata_mem)
4392 // if we ran out of space on the last frame, free the old memory now
4393 while (r_framedata_mem->purge)
4395 // repeatedly remove the second item in the list, leaving only head
4396 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4397 Mem_Free(r_framedata_mem->purge);
4398 r_framedata_mem->purge = next;
4400 // reset the current mem pointer
4401 r_framedata_mem->current = 0;
4402 r_framedata_mem->mark = 0;
4405 void *R_FrameData_Alloc(size_t size)
4409 // align to 16 byte boundary - the data pointer is already aligned, so we
4410 // only need to ensure the size of every allocation is also aligned
4411 size = (size + 15) & ~15;
4413 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4415 // emergency - we ran out of space, allocate more memory
4416 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4417 R_FrameData_Resize();
4420 data = r_framedata_mem->data + r_framedata_mem->current;
4421 r_framedata_mem->current += size;
4423 // count the usage for stats
4424 r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4425 r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4427 return (void *)data;
4430 void *R_FrameData_Store(size_t size, void *data)
4432 void *d = R_FrameData_Alloc(size);
4434 memcpy(d, data, size);
4438 void R_FrameData_SetMark(void)
4440 if (!r_framedata_mem)
4442 r_framedata_mem->mark = r_framedata_mem->current;
4445 void R_FrameData_ReturnToMark(void)
4447 if (!r_framedata_mem)
4449 r_framedata_mem->current = r_framedata_mem->mark;
4452 //==================================================================================
4454 // LordHavoc: animcache originally written by Echon, rewritten since then
4457 * Animation cache prevents re-generating mesh data for an animated model
4458 * multiple times in one frame for lighting, shadowing, reflections, etc.
4461 void R_AnimCache_Free(void)
4465 void R_AnimCache_ClearCache(void)
4468 entity_render_t *ent;
4470 for (i = 0;i < r_refdef.scene.numentities;i++)
4472 ent = r_refdef.scene.entities[i];
4473 ent->animcache_vertex3f = NULL;
4474 ent->animcache_normal3f = NULL;
4475 ent->animcache_svector3f = NULL;
4476 ent->animcache_tvector3f = NULL;
4477 ent->animcache_vertexmesh = NULL;
4478 ent->animcache_vertex3fbuffer = NULL;
4479 ent->animcache_vertexmeshbuffer = NULL;
4483 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4487 // check if we need the meshbuffers
4488 if (!vid.useinterleavedarrays)
4491 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4492 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4493 // TODO: upload vertex3f buffer?
4494 if (ent->animcache_vertexmesh)
4496 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4497 for (i = 0;i < numvertices;i++)
4498 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4499 if (ent->animcache_svector3f)
4500 for (i = 0;i < numvertices;i++)
4501 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4502 if (ent->animcache_tvector3f)
4503 for (i = 0;i < numvertices;i++)
4504 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4505 if (ent->animcache_normal3f)
4506 for (i = 0;i < numvertices;i++)
4507 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4508 // TODO: upload vertexmeshbuffer?
4512 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4514 dp_model_t *model = ent->model;
4516 // see if it's already cached this frame
4517 if (ent->animcache_vertex3f)
4519 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4520 if (wantnormals || wanttangents)
4522 if (ent->animcache_normal3f)
4523 wantnormals = false;
4524 if (ent->animcache_svector3f)
4525 wanttangents = false;
4526 if (wantnormals || wanttangents)
4528 numvertices = model->surfmesh.num_vertices;
4530 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4533 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4534 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4536 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4537 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4543 // see if this ent is worth caching
4544 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4546 // get some memory for this entity and generate mesh data
4547 numvertices = model->surfmesh.num_vertices;
4548 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4550 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4553 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4554 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4556 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4557 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4562 void R_AnimCache_CacheVisibleEntities(void)
4565 qboolean wantnormals = true;
4566 qboolean wanttangents = !r_showsurfaces.integer;
4568 switch(vid.renderpath)
4570 case RENDERPATH_GL20:
4571 case RENDERPATH_D3D9:
4572 case RENDERPATH_D3D10:
4573 case RENDERPATH_D3D11:
4574 case RENDERPATH_GLES2:
4576 case RENDERPATH_GL11:
4577 case RENDERPATH_GL13:
4578 case RENDERPATH_GLES1:
4579 wanttangents = false;
4581 case RENDERPATH_SOFT:
4585 if (r_shownormals.integer)
4586 wanttangents = wantnormals = true;
4588 // TODO: thread this
4589 // NOTE: R_PrepareRTLights() also caches entities
4591 for (i = 0;i < r_refdef.scene.numentities;i++)
4592 if (r_refdef.viewcache.entityvisible[i])
4593 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4596 //==================================================================================
4598 static void R_View_UpdateEntityLighting (void)
4601 entity_render_t *ent;
4602 vec3_t tempdiffusenormal, avg;
4603 vec_t f, fa, fd, fdd;
4604 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4606 for (i = 0;i < r_refdef.scene.numentities;i++)
4608 ent = r_refdef.scene.entities[i];
4610 // skip unseen models
4611 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4615 if (ent->model && ent->model->brush.num_leafs)
4617 // TODO: use modellight for r_ambient settings on world?
4618 VectorSet(ent->modellight_ambient, 0, 0, 0);
4619 VectorSet(ent->modellight_diffuse, 0, 0, 0);
4620 VectorSet(ent->modellight_lightdir, 0, 0, 1);
4624 // fetch the lighting from the worldmodel data
4625 VectorClear(ent->modellight_ambient);
4626 VectorClear(ent->modellight_diffuse);
4627 VectorClear(tempdiffusenormal);
4628 if (ent->flags & RENDER_LIGHT)
4631 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4633 // complete lightning for lit sprites
4634 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4635 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4637 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4638 org[2] = org[2] + r_overheadsprites_pushback.value;
4639 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4642 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4644 if(ent->flags & RENDER_EQUALIZE)
4646 // first fix up ambient lighting...
4647 if(r_equalize_entities_minambient.value > 0)
4649 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4652 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4653 if(fa < r_equalize_entities_minambient.value * fd)
4656 // fa'/fd' = minambient
4657 // fa'+0.25*fd' = fa+0.25*fd
4659 // fa' = fd' * minambient
4660 // fd'*(0.25+minambient) = fa+0.25*fd
4662 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4663 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4665 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4666 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
4667 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4668 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4673 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4675 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4676 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4680 // adjust brightness and saturation to target
4681 avg[0] = avg[1] = avg[2] = fa / f;
4682 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4683 avg[0] = avg[1] = avg[2] = fd / f;
4684 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4690 VectorSet(ent->modellight_ambient, 1, 1, 1);
4692 // move the light direction into modelspace coordinates for lighting code
4693 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4694 if(VectorLength2(ent->modellight_lightdir) == 0)
4695 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4696 VectorNormalize(ent->modellight_lightdir);
4700 #define MAX_LINEOFSIGHTTRACES 64
4702 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4705 vec3_t boxmins, boxmaxs;
4708 dp_model_t *model = r_refdef.scene.worldmodel;
4710 if (!model || !model->brush.TraceLineOfSight)
4713 // expand the box a little
4714 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4715 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4716 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4717 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4718 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4719 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4721 // return true if eye is inside enlarged box
4722 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4726 VectorCopy(eye, start);
4727 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4728 if (model->brush.TraceLineOfSight(model, start, end))
4731 // try various random positions
4732 for (i = 0;i < numsamples;i++)
4734 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4735 if (model->brush.TraceLineOfSight(model, start, end))
4743 static void R_View_UpdateEntityVisible (void)
4748 entity_render_t *ent;
4750 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4751 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4752 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
4753 : RENDER_EXTERIORMODEL;
4754 if (!r_drawviewmodel.integer)
4755 renderimask |= RENDER_VIEWMODEL;
4756 if (!r_drawexteriormodel.integer)
4757 renderimask |= RENDER_EXTERIORMODEL;
4758 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4760 // worldmodel can check visibility
4761 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4762 for (i = 0;i < r_refdef.scene.numentities;i++)
4764 ent = r_refdef.scene.entities[i];
4765 if (!(ent->flags & renderimask))
4766 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)))
4767 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))
4768 r_refdef.viewcache.entityvisible[i] = true;
4773 // no worldmodel or it can't check visibility
4774 for (i = 0;i < r_refdef.scene.numentities;i++)
4776 ent = r_refdef.scene.entities[i];
4777 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));
4780 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
4781 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4783 for (i = 0;i < r_refdef.scene.numentities;i++)
4785 if (!r_refdef.viewcache.entityvisible[i])
4787 ent = r_refdef.scene.entities[i];
4788 if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4790 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4792 continue; // temp entities do pvs only
4793 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4794 ent->last_trace_visibility = realtime;
4795 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4796 r_refdef.viewcache.entityvisible[i] = 0;
4802 /// only used if skyrendermasked, and normally returns false
4803 int R_DrawBrushModelsSky (void)
4806 entity_render_t *ent;
4809 for (i = 0;i < r_refdef.scene.numentities;i++)
4811 if (!r_refdef.viewcache.entityvisible[i])
4813 ent = r_refdef.scene.entities[i];
4814 if (!ent->model || !ent->model->DrawSky)
4816 ent->model->DrawSky(ent);
4822 static void R_DrawNoModel(entity_render_t *ent);
4823 static void R_DrawModels(void)
4826 entity_render_t *ent;
4828 for (i = 0;i < r_refdef.scene.numentities;i++)
4830 if (!r_refdef.viewcache.entityvisible[i])
4832 ent = r_refdef.scene.entities[i];
4833 r_refdef.stats.entities++;
4835 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
4838 Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
4839 Con_Printf("R_DrawModels\n");
4840 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]);
4841 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);
4842 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);
4845 if (ent->model && ent->model->Draw != NULL)
4846 ent->model->Draw(ent);
4852 static void R_DrawModelsDepth(void)
4855 entity_render_t *ent;
4857 for (i = 0;i < r_refdef.scene.numentities;i++)
4859 if (!r_refdef.viewcache.entityvisible[i])
4861 ent = r_refdef.scene.entities[i];
4862 if (ent->model && ent->model->DrawDepth != NULL)
4863 ent->model->DrawDepth(ent);
4867 static void R_DrawModelsDebug(void)
4870 entity_render_t *ent;
4872 for (i = 0;i < r_refdef.scene.numentities;i++)
4874 if (!r_refdef.viewcache.entityvisible[i])
4876 ent = r_refdef.scene.entities[i];
4877 if (ent->model && ent->model->DrawDebug != NULL)
4878 ent->model->DrawDebug(ent);
4882 static void R_DrawModelsAddWaterPlanes(void)
4885 entity_render_t *ent;
4887 for (i = 0;i < r_refdef.scene.numentities;i++)
4889 if (!r_refdef.viewcache.entityvisible[i])
4891 ent = r_refdef.scene.entities[i];
4892 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4893 ent->model->DrawAddWaterPlanes(ent);
4897 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4899 if (r_hdr_irisadaptation.integer)
4903 vec3_t diffusenormal;
4908 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4909 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
4910 brightness = max(0.0000001f, brightness);
4911 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4912 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4913 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
4914 current = r_hdr_irisadaptation_value.value;
4916 current = min(current + adjust, goal);
4917 else if (current > goal)
4918 current = max(current - adjust, goal);
4919 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4920 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4922 else if (r_hdr_irisadaptation_value.value != 1.0f)
4923 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4926 static void R_View_SetFrustum(const int *scissor)
4929 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
4930 vec3_t forward, left, up, origin, v;
4934 // flipped x coordinates (because x points left here)
4935 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4936 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4938 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
4939 switch(vid.renderpath)
4941 case RENDERPATH_D3D9:
4942 case RENDERPATH_D3D10:
4943 case RENDERPATH_D3D11:
4944 // non-flipped y coordinates
4945 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4946 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4948 case RENDERPATH_SOFT:
4949 case RENDERPATH_GL11:
4950 case RENDERPATH_GL13:
4951 case RENDERPATH_GL20:
4952 case RENDERPATH_GLES1:
4953 case RENDERPATH_GLES2:
4954 // non-flipped y coordinates
4955 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4956 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4961 // we can't trust r_refdef.view.forward and friends in reflected scenes
4962 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4965 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4966 r_refdef.view.frustum[0].normal[1] = 0 - 0;
4967 r_refdef.view.frustum[0].normal[2] = -1 - 0;
4968 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4969 r_refdef.view.frustum[1].normal[1] = 0 + 0;
4970 r_refdef.view.frustum[1].normal[2] = -1 + 0;
4971 r_refdef.view.frustum[2].normal[0] = 0 - 0;
4972 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4973 r_refdef.view.frustum[2].normal[2] = -1 - 0;
4974 r_refdef.view.frustum[3].normal[0] = 0 + 0;
4975 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4976 r_refdef.view.frustum[3].normal[2] = -1 + 0;
4980 zNear = r_refdef.nearclip;
4981 nudge = 1.0 - 1.0 / (1<<23);
4982 r_refdef.view.frustum[4].normal[0] = 0 - 0;
4983 r_refdef.view.frustum[4].normal[1] = 0 - 0;
4984 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4985 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4986 r_refdef.view.frustum[5].normal[0] = 0 + 0;
4987 r_refdef.view.frustum[5].normal[1] = 0 + 0;
4988 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
4989 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
4995 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
4996 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
4997 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
4998 r_refdef.view.frustum[0].dist = m[15] - m[12];
5000 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5001 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5002 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5003 r_refdef.view.frustum[1].dist = m[15] + m[12];
5005 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5006 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5007 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5008 r_refdef.view.frustum[2].dist = m[15] - m[13];
5010 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5011 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5012 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5013 r_refdef.view.frustum[3].dist = m[15] + m[13];
5015 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5016 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5017 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5018 r_refdef.view.frustum[4].dist = m[15] - m[14];
5020 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5021 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5022 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5023 r_refdef.view.frustum[5].dist = m[15] + m[14];
5026 if (r_refdef.view.useperspective)
5028 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5029 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]);
5030 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]);
5031 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]);
5032 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]);
5034 // then the normals from the corners relative to origin
5035 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5036 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5037 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5038 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5040 // in a NORMAL view, forward cross left == up
5041 // in a REFLECTED view, forward cross left == down
5042 // so our cross products above need to be adjusted for a left handed coordinate system
5043 CrossProduct(forward, left, v);
5044 if(DotProduct(v, up) < 0)
5046 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5047 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5048 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5049 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5052 // Leaving those out was a mistake, those were in the old code, and they
5053 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5054 // I couldn't reproduce it after adding those normalizations. --blub
5055 VectorNormalize(r_refdef.view.frustum[0].normal);
5056 VectorNormalize(r_refdef.view.frustum[1].normal);
5057 VectorNormalize(r_refdef.view.frustum[2].normal);
5058 VectorNormalize(r_refdef.view.frustum[3].normal);
5060 // make the corners absolute
5061 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5062 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5063 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5064 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5067 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5069 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5070 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5071 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5072 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5073 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5077 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5078 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5079 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5080 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5081 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5082 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5083 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5084 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5085 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5086 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5088 r_refdef.view.numfrustumplanes = 5;
5090 if (r_refdef.view.useclipplane)
5092 r_refdef.view.numfrustumplanes = 6;
5093 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5096 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5097 PlaneClassify(r_refdef.view.frustum + i);
5099 // LordHavoc: note to all quake engine coders, Quake had a special case
5100 // for 90 degrees which assumed a square view (wrong), so I removed it,
5101 // Quake2 has it disabled as well.
5103 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5104 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5105 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5106 //PlaneClassify(&frustum[0]);
5108 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5109 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5110 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5111 //PlaneClassify(&frustum[1]);
5113 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5114 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5115 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5116 //PlaneClassify(&frustum[2]);
5118 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5119 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5120 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5121 //PlaneClassify(&frustum[3]);
5124 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5125 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5126 //PlaneClassify(&frustum[4]);
5129 void R_View_UpdateWithScissor(const int *myscissor)
5131 R_Main_ResizeViewCache();
5132 R_View_SetFrustum(myscissor);
5133 R_View_WorldVisibility(r_refdef.view.useclipplane);
5134 R_View_UpdateEntityVisible();
5135 R_View_UpdateEntityLighting();
5138 void R_View_Update(void)
5140 R_Main_ResizeViewCache();
5141 R_View_SetFrustum(NULL);
5142 R_View_WorldVisibility(r_refdef.view.useclipplane);
5143 R_View_UpdateEntityVisible();
5144 R_View_UpdateEntityLighting();
5147 float viewscalefpsadjusted = 1.0f;
5149 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5151 float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5152 scale = bound(0.03125f, scale, 1.0f);
5153 *outwidth = (int)ceil(width * scale);
5154 *outheight = (int)ceil(height * scale);
5157 void R_Mesh_SetMainRenderTargets(void)
5159 if (r_bloomstate.fbo_framebuffer)
5160 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5162 R_Mesh_ResetRenderTargets();
5165 void R_SetupView(qboolean allowwaterclippingplane)
5167 const float *customclipplane = NULL;
5169 int scaledwidth, scaledheight;
5170 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5172 // LordHavoc: couldn't figure out how to make this approach the
5173 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5174 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5175 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5176 dist = r_refdef.view.clipplane.dist;
5177 plane[0] = r_refdef.view.clipplane.normal[0];
5178 plane[1] = r_refdef.view.clipplane.normal[1];
5179 plane[2] = r_refdef.view.clipplane.normal[2];
5181 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5184 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5185 if (!r_refdef.view.useperspective)
5186 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);
5187 else if (vid.stencil && r_useinfinitefarclip.integer)
5188 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);
5190 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);
5191 R_Mesh_SetMainRenderTargets();
5192 R_SetViewport(&r_refdef.view.viewport);
5193 if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5195 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5196 float screenplane[4];
5197 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5198 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5199 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5200 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5201 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5205 void R_EntityMatrix(const matrix4x4_t *matrix)
5207 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5209 gl_modelmatrixchanged = false;
5210 gl_modelmatrix = *matrix;
5211 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5212 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5213 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5214 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5216 switch(vid.renderpath)
5218 case RENDERPATH_D3D9:
5220 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5221 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5224 case RENDERPATH_D3D10:
5225 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5227 case RENDERPATH_D3D11:
5228 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5230 case RENDERPATH_GL11:
5231 case RENDERPATH_GL13:
5232 case RENDERPATH_GLES1:
5233 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5235 case RENDERPATH_SOFT:
5236 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5237 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5239 case RENDERPATH_GL20:
5240 case RENDERPATH_GLES2:
5241 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5242 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5248 void R_ResetViewRendering2D(void)
5250 r_viewport_t viewport;
5253 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5254 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);
5255 R_Mesh_ResetRenderTargets();
5256 R_SetViewport(&viewport);
5257 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5258 GL_Color(1, 1, 1, 1);
5259 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5260 GL_BlendFunc(GL_ONE, GL_ZERO);
5261 GL_ScissorTest(false);
5262 GL_DepthMask(false);
5263 GL_DepthRange(0, 1);
5264 GL_DepthTest(false);
5265 GL_DepthFunc(GL_LEQUAL);
5266 R_EntityMatrix(&identitymatrix);
5267 R_Mesh_ResetTextureState();
5268 GL_PolygonOffset(0, 0);
5269 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5270 switch(vid.renderpath)
5272 case RENDERPATH_GL11:
5273 case RENDERPATH_GL13:
5274 case RENDERPATH_GL20:
5275 case RENDERPATH_GLES1:
5276 case RENDERPATH_GLES2:
5277 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5279 case RENDERPATH_D3D9:
5280 case RENDERPATH_D3D10:
5281 case RENDERPATH_D3D11:
5282 case RENDERPATH_SOFT:
5285 GL_CullFace(GL_NONE);
5288 void R_ResetViewRendering3D(void)
5293 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5294 GL_Color(1, 1, 1, 1);
5295 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5296 GL_BlendFunc(GL_ONE, GL_ZERO);
5297 GL_ScissorTest(true);
5299 GL_DepthRange(0, 1);
5301 GL_DepthFunc(GL_LEQUAL);
5302 R_EntityMatrix(&identitymatrix);
5303 R_Mesh_ResetTextureState();
5304 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5305 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5306 switch(vid.renderpath)
5308 case RENDERPATH_GL11:
5309 case RENDERPATH_GL13:
5310 case RENDERPATH_GL20:
5311 case RENDERPATH_GLES1:
5312 case RENDERPATH_GLES2:
5313 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5315 case RENDERPATH_D3D9:
5316 case RENDERPATH_D3D10:
5317 case RENDERPATH_D3D11:
5318 case RENDERPATH_SOFT:
5321 GL_CullFace(r_refdef.view.cullface_back);
5326 R_RenderView_UpdateViewVectors
5329 static void R_RenderView_UpdateViewVectors(void)
5331 // break apart the view matrix into vectors for various purposes
5332 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5333 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5334 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5335 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5336 // make an inverted copy of the view matrix for tracking sprites
5337 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5340 void R_RenderScene(void);
5341 void R_RenderWaterPlanes(void);
5343 static void R_Water_StartFrame(void)
5346 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5347 r_waterstate_waterplane_t *p;
5349 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5352 switch(vid.renderpath)
5354 case RENDERPATH_GL20:
5355 case RENDERPATH_D3D9:
5356 case RENDERPATH_D3D10:
5357 case RENDERPATH_D3D11:
5358 case RENDERPATH_SOFT:
5359 case RENDERPATH_GLES2:
5361 case RENDERPATH_GL11:
5362 case RENDERPATH_GL13:
5363 case RENDERPATH_GLES1:
5367 // set waterwidth and waterheight to the water resolution that will be
5368 // used (often less than the screen resolution for faster rendering)
5369 R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5371 // calculate desired texture sizes
5372 // can't use water if the card does not support the texture size
5373 if (!r_water.integer || r_showsurfaces.integer)
5374 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5375 else if (vid.support.arb_texture_non_power_of_two)
5377 texturewidth = waterwidth;
5378 textureheight = waterheight;
5379 camerawidth = waterwidth;
5380 cameraheight = waterheight;
5384 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5385 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5386 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
5387 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
5390 // allocate textures as needed
5391 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5393 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5394 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5396 if (p->texture_refraction)
5397 R_FreeTexture(p->texture_refraction);
5398 p->texture_refraction = NULL;
5399 if (p->texture_reflection)
5400 R_FreeTexture(p->texture_reflection);
5401 p->texture_reflection = NULL;
5402 if (p->texture_camera)
5403 R_FreeTexture(p->texture_camera);
5404 p->texture_camera = NULL;
5406 memset(&r_waterstate, 0, sizeof(r_waterstate));
5407 r_waterstate.texturewidth = texturewidth;
5408 r_waterstate.textureheight = textureheight;
5409 r_waterstate.camerawidth = camerawidth;
5410 r_waterstate.cameraheight = cameraheight;
5413 if (r_waterstate.texturewidth)
5415 int scaledwidth, scaledheight;
5417 r_waterstate.enabled = true;
5419 // when doing a reduced render (HDR) we want to use a smaller area
5420 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5421 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5422 R_GetScaledViewSize(r_waterstate.waterwidth, r_waterstate.waterheight, &scaledwidth, &scaledheight);
5424 // set up variables that will be used in shader setup
5425 r_waterstate.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5426 r_waterstate.screenscale[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5427 r_waterstate.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5428 r_waterstate.screencenter[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5431 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5432 r_waterstate.numwaterplanes = 0;
5435 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5437 int triangleindex, planeindex;
5443 r_waterstate_waterplane_t *p;
5444 texture_t *t = R_GetCurrentTexture(surface->texture);
5446 // just use the first triangle with a valid normal for any decisions
5447 VectorClear(normal);
5448 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5450 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5451 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5452 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5453 TriangleNormal(vert[0], vert[1], vert[2], normal);
5454 if (VectorLength2(normal) >= 0.001)
5458 VectorCopy(normal, plane.normal);
5459 VectorNormalize(plane.normal);
5460 plane.dist = DotProduct(vert[0], plane.normal);
5461 PlaneClassify(&plane);
5462 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5464 // skip backfaces (except if nocullface is set)
5465 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5467 VectorNegate(plane.normal, plane.normal);
5469 PlaneClassify(&plane);
5473 // find a matching plane if there is one
5474 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5475 if(p->camera_entity == t->camera_entity)
5476 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5478 if (planeindex >= r_waterstate.maxwaterplanes)
5479 return; // nothing we can do, out of planes
5481 // if this triangle does not fit any known plane rendered this frame, add one
5482 if (planeindex >= r_waterstate.numwaterplanes)
5484 // store the new plane
5485 r_waterstate.numwaterplanes++;
5487 // clear materialflags and pvs
5488 p->materialflags = 0;
5489 p->pvsvalid = false;
5490 p->camera_entity = t->camera_entity;
5491 VectorCopy(surface->mins, p->mins);
5492 VectorCopy(surface->maxs, p->maxs);
5497 p->mins[0] = min(p->mins[0], surface->mins[0]);
5498 p->mins[1] = min(p->mins[1], surface->mins[1]);
5499 p->mins[2] = min(p->mins[2], surface->mins[2]);
5500 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5501 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5502 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5504 // merge this surface's materialflags into the waterplane
5505 p->materialflags |= t->currentmaterialflags;
5506 if(!(p->materialflags & MATERIALFLAG_CAMERA))
5508 // merge this surface's PVS into the waterplane
5509 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5510 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5511 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5513 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5519 static void R_Water_ProcessPlanes(void)
5522 r_refdef_view_t originalview;
5523 r_refdef_view_t myview;
5525 r_waterstate_waterplane_t *p;
5528 originalview = r_refdef.view;
5530 // make sure enough textures are allocated
5531 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5533 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5535 if (!p->texture_refraction)
5536 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);
5537 if (!p->texture_refraction)
5540 else if (p->materialflags & MATERIALFLAG_CAMERA)
5542 if (!p->texture_camera)
5543 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);
5544 if (!p->texture_camera)
5548 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5550 if (!p->texture_reflection)
5551 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);
5552 if (!p->texture_reflection)
5558 r_refdef.view = originalview;
5559 r_refdef.view.showdebug = false;
5560 r_refdef.view.width = r_waterstate.waterwidth;
5561 r_refdef.view.height = r_waterstate.waterheight;
5562 r_refdef.view.useclipplane = true;
5563 myview = r_refdef.view;
5564 r_waterstate.renderingscene = true;
5565 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5567 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5569 r_refdef.view = myview;
5570 if(r_water_scissormode.integer)
5573 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5574 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5577 // render reflected scene and copy into texture
5578 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5579 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5580 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5581 r_refdef.view.clipplane = p->plane;
5583 // reverse the cullface settings for this render
5584 r_refdef.view.cullface_front = GL_FRONT;
5585 r_refdef.view.cullface_back = GL_BACK;
5586 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5588 r_refdef.view.usecustompvs = true;
5590 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5592 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5595 R_ResetViewRendering3D();
5596 R_ClearScreen(r_refdef.fogenabled);
5597 if(r_water_scissormode.integer & 2)
5598 R_View_UpdateWithScissor(myscissor);
5601 if(r_water_scissormode.integer & 1)
5602 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5605 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);
5608 // render the normal view scene and copy into texture
5609 // (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)
5610 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5612 r_refdef.view = myview;
5613 if(r_water_scissormode.integer)
5616 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5617 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5620 r_waterstate.renderingrefraction = true;
5622 r_refdef.view.clipplane = p->plane;
5623 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5624 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5626 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5628 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5629 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5630 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5631 R_RenderView_UpdateViewVectors();
5632 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5634 r_refdef.view.usecustompvs = true;
5635 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);
5639 PlaneClassify(&r_refdef.view.clipplane);
5641 R_ResetViewRendering3D();
5642 R_ClearScreen(r_refdef.fogenabled);
5643 if(r_water_scissormode.integer & 2)
5644 R_View_UpdateWithScissor(myscissor);
5647 if(r_water_scissormode.integer & 1)
5648 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5651 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);
5652 r_waterstate.renderingrefraction = false;
5654 else if (p->materialflags & MATERIALFLAG_CAMERA)
5656 r_refdef.view = myview;
5658 r_refdef.view.clipplane = p->plane;
5659 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5660 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5662 r_refdef.view.width = r_waterstate.camerawidth;
5663 r_refdef.view.height = r_waterstate.cameraheight;
5664 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5665 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5667 if(p->camera_entity)
5669 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5670 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5673 // note: all of the view is used for displaying... so
5674 // there is no use in scissoring
5676 // reverse the cullface settings for this render
5677 r_refdef.view.cullface_front = GL_FRONT;
5678 r_refdef.view.cullface_back = GL_BACK;
5679 // also reverse the view matrix
5680 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
5681 R_RenderView_UpdateViewVectors();
5682 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5684 r_refdef.view.usecustompvs = true;
5685 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);
5688 // camera needs no clipplane
5689 r_refdef.view.useclipplane = false;
5691 PlaneClassify(&r_refdef.view.clipplane);
5693 R_ResetViewRendering3D();
5694 R_ClearScreen(r_refdef.fogenabled);
5698 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);
5699 r_waterstate.renderingrefraction = false;
5703 if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5704 r_waterstate.renderingscene = false;
5705 r_refdef.view = originalview;
5706 R_ResetViewRendering3D();
5707 R_ClearScreen(r_refdef.fogenabled);
5711 r_refdef.view = originalview;
5712 r_waterstate.renderingscene = false;
5713 Cvar_SetValueQuick(&r_water, 0);
5714 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
5718 void R_Bloom_StartFrame(void)
5720 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5721 int viewwidth, viewheight;
5724 if (r_viewscale_fpsscaling.integer)
5726 double actualframetime;
5727 double targetframetime;
5729 actualframetime = r_refdef.lastdrawscreentime;
5730 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5731 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5732 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5733 if (r_viewscale_fpsscaling_stepsize.value > 0)
5734 adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5735 viewscalefpsadjusted += adjust;
5736 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5739 viewscalefpsadjusted = 1.0f;
5741 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5743 switch(vid.renderpath)
5745 case RENDERPATH_GL20:
5746 case RENDERPATH_D3D9:
5747 case RENDERPATH_D3D10:
5748 case RENDERPATH_D3D11:
5749 case RENDERPATH_SOFT:
5750 case RENDERPATH_GLES2:
5752 case RENDERPATH_GL11:
5753 case RENDERPATH_GL13:
5754 case RENDERPATH_GLES1:
5758 // set bloomwidth and bloomheight to the bloom resolution that will be
5759 // used (often less than the screen resolution for faster rendering)
5760 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5761 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5762 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5763 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5764 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5766 // calculate desired texture sizes
5767 if (vid.support.arb_texture_non_power_of_two)
5769 screentexturewidth = vid.width;
5770 screentextureheight = vid.height;
5771 bloomtexturewidth = r_bloomstate.bloomwidth;
5772 bloomtextureheight = r_bloomstate.bloomheight;
5776 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
5777 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
5778 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
5779 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
5782 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))
5784 Cvar_SetValueQuick(&r_hdr, 0);
5785 Cvar_SetValueQuick(&r_bloom, 0);
5786 Cvar_SetValueQuick(&r_motionblur, 0);
5787 Cvar_SetValueQuick(&r_damageblur, 0);
5790 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)
5791 screentexturewidth = screentextureheight = 0;
5792 if (!r_hdr.integer && !r_bloom.integer)
5793 bloomtexturewidth = bloomtextureheight = 0;
5795 textype = TEXTYPE_COLORBUFFER;
5796 switch (vid.renderpath)
5798 case RENDERPATH_GL20:
5799 case RENDERPATH_GLES2:
5800 if (vid.support.ext_framebuffer_object)
5802 if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5803 if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5806 case RENDERPATH_GL11:
5807 case RENDERPATH_GL13:
5808 case RENDERPATH_GLES1:
5809 case RENDERPATH_D3D9:
5810 case RENDERPATH_D3D10:
5811 case RENDERPATH_D3D11:
5812 case RENDERPATH_SOFT:
5816 // allocate textures as needed
5817 if (r_bloomstate.screentexturewidth != screentexturewidth
5818 || r_bloomstate.screentextureheight != screentextureheight
5819 || r_bloomstate.bloomtexturewidth != bloomtexturewidth
5820 || r_bloomstate.bloomtextureheight != bloomtextureheight
5821 || r_bloomstate.texturetype != textype
5822 || r_bloomstate.viewfbo != r_viewfbo.integer)
5824 if (r_bloomstate.texture_bloom)
5825 R_FreeTexture(r_bloomstate.texture_bloom);
5826 r_bloomstate.texture_bloom = NULL;
5827 if (r_bloomstate.texture_screen)
5828 R_FreeTexture(r_bloomstate.texture_screen);
5829 r_bloomstate.texture_screen = NULL;
5830 if (r_bloomstate.fbo_framebuffer)
5831 R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
5832 r_bloomstate.fbo_framebuffer = 0;
5833 if (r_bloomstate.texture_framebuffercolor)
5834 R_FreeTexture(r_bloomstate.texture_framebuffercolor);
5835 r_bloomstate.texture_framebuffercolor = NULL;
5836 if (r_bloomstate.texture_framebufferdepth)
5837 R_FreeTexture(r_bloomstate.texture_framebufferdepth);
5838 r_bloomstate.texture_framebufferdepth = NULL;
5839 r_bloomstate.screentexturewidth = screentexturewidth;
5840 r_bloomstate.screentextureheight = screentextureheight;
5841 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5842 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);
5843 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
5845 // FIXME: choose depth bits based on a cvar
5846 r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
5847 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);
5848 r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5849 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5850 // render depth into one texture and normalmap into the other
5854 qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5855 qglReadBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5856 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
5857 if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
5858 Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
5861 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5862 r_bloomstate.bloomtextureheight = bloomtextureheight;
5863 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5864 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);
5865 r_bloomstate.viewfbo = r_viewfbo.integer;
5866 r_bloomstate.texturetype = textype;
5869 // when doing a reduced render (HDR) we want to use a smaller area
5870 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5871 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5872 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5873 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5874 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5876 // set up a texcoord array for the full resolution screen image
5877 // (we have to keep this around to copy back during final render)
5878 r_bloomstate.screentexcoord2f[0] = 0;
5879 r_bloomstate.screentexcoord2f[1] = (float)viewheight / (float)r_bloomstate.screentextureheight;
5880 r_bloomstate.screentexcoord2f[2] = (float)viewwidth / (float)r_bloomstate.screentexturewidth;
5881 r_bloomstate.screentexcoord2f[3] = (float)viewheight / (float)r_bloomstate.screentextureheight;
5882 r_bloomstate.screentexcoord2f[4] = (float)viewwidth / (float)r_bloomstate.screentexturewidth;
5883 r_bloomstate.screentexcoord2f[5] = 0;
5884 r_bloomstate.screentexcoord2f[6] = 0;
5885 r_bloomstate.screentexcoord2f[7] = 0;
5887 // set up a texcoord array for the reduced resolution bloom image
5888 // (which will be additive blended over the screen image)
5889 r_bloomstate.bloomtexcoord2f[0] = 0;
5890 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5891 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5892 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5893 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5894 r_bloomstate.bloomtexcoord2f[5] = 0;
5895 r_bloomstate.bloomtexcoord2f[6] = 0;
5896 r_bloomstate.bloomtexcoord2f[7] = 0;
5898 switch(vid.renderpath)
5900 case RENDERPATH_GL11:
5901 case RENDERPATH_GL13:
5902 case RENDERPATH_GL20:
5903 case RENDERPATH_SOFT:
5904 case RENDERPATH_GLES1:
5905 case RENDERPATH_GLES2:
5907 case RENDERPATH_D3D9:
5908 case RENDERPATH_D3D10:
5909 case RENDERPATH_D3D11:
5912 for (i = 0;i < 4;i++)
5914 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
5915 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
5916 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
5917 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
5923 if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth)
5925 r_bloomstate.enabled = true;
5926 r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer;
5929 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);
5931 if (r_bloomstate.fbo_framebuffer)
5932 r_refdef.view.clear = true;
5935 void R_Bloom_CopyBloomTexture(float colorscale)
5937 r_refdef.stats.bloom++;
5939 // scale down screen texture to the bloom texture size
5941 R_Mesh_SetMainRenderTargets();
5942 R_SetViewport(&r_bloomstate.viewport);
5943 GL_BlendFunc(GL_ONE, GL_ZERO);
5944 GL_Color(colorscale, colorscale, colorscale, 1);
5945 // 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...
5946 switch(vid.renderpath)
5948 case RENDERPATH_GL11:
5949 case RENDERPATH_GL13:
5950 case RENDERPATH_GL20:
5951 case RENDERPATH_GLES1:
5952 case RENDERPATH_GLES2:
5953 case RENDERPATH_SOFT:
5954 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5956 case RENDERPATH_D3D9:
5957 case RENDERPATH_D3D10:
5958 case RENDERPATH_D3D11:
5959 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5962 // TODO: do boxfilter scale-down in shader?
5963 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5964 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5965 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5967 // we now have a bloom image in the framebuffer
5968 // copy it into the bloom image texture for later processing
5969 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);
5970 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5973 void R_Bloom_CopyHDRTexture(void)
5975 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);
5976 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5979 void R_Bloom_MakeTexture(void)
5982 float xoffset, yoffset, r, brighten;
5984 r_refdef.stats.bloom++;
5986 R_ResetViewRendering2D();
5988 // we have a bloom image in the framebuffer
5990 R_SetViewport(&r_bloomstate.viewport);
5992 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
5995 r = bound(0, r_bloom_colorexponent.value / x, 1);
5996 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5998 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
5999 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
6000 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6001 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6003 // copy the vertically blurred bloom view to a texture
6004 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);
6005 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6008 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
6009 brighten = r_bloom_brighten.value;
6010 if (r_bloomstate.hdr)
6011 brighten *= r_hdr_range.value;
6012 brighten = sqrt(brighten);
6014 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6015 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
6017 for (dir = 0;dir < 2;dir++)
6019 // blend on at multiple vertical offsets to achieve a vertical blur
6020 // TODO: do offset blends using GLSL
6021 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6022 GL_BlendFunc(GL_ONE, GL_ZERO);
6023 for (x = -range;x <= range;x++)
6025 if (!dir){xoffset = 0;yoffset = x;}
6026 else {xoffset = x;yoffset = 0;}
6027 xoffset /= (float)r_bloomstate.bloomtexturewidth;
6028 yoffset /= (float)r_bloomstate.bloomtextureheight;
6029 // compute a texcoord array with the specified x and y offset
6030 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
6031 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6032 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6033 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6034 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6035 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
6036 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
6037 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
6038 // this r value looks like a 'dot' particle, fading sharply to
6039 // black at the edges
6040 // (probably not realistic but looks good enough)
6041 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6042 //r = brighten/(range*2+1);
6043 r = brighten / (range * 2 + 1);
6045 r *= (1 - x*x/(float)(range*range));
6046 GL_Color(r, r, r, 1);
6047 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6048 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6049 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6050 GL_BlendFunc(GL_ONE, GL_ONE);
6053 // copy the vertically blurred bloom view to a texture
6054 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);
6055 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6059 void R_HDR_RenderBloomTexture(void)
6061 int oldwidth, oldheight;
6062 float oldcolorscale;
6063 qboolean oldwaterstate;
6065 oldwaterstate = r_waterstate.enabled;
6066 oldcolorscale = r_refdef.view.colorscale;
6067 oldwidth = r_refdef.view.width;
6068 oldheight = r_refdef.view.height;
6069 r_refdef.view.width = r_bloomstate.bloomwidth;
6070 r_refdef.view.height = r_bloomstate.bloomheight;
6072 if(r_hdr.integer < 2)
6073 r_waterstate.enabled = false;
6075 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
6076 // TODO: add exposure compensation features
6077 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6079 r_refdef.view.showdebug = false;
6080 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6082 R_ResetViewRendering3D();
6084 R_ClearScreen(r_refdef.fogenabled);
6085 if (r_timereport_active)
6086 R_TimeReport("HDRclear");
6089 if (r_timereport_active)
6090 R_TimeReport("visibility");
6092 // only do secondary renders with HDR if r_hdr is 2 or higher
6093 r_waterstate.numwaterplanes = 0;
6094 if (r_waterstate.enabled)
6095 R_RenderWaterPlanes();
6097 r_refdef.view.showdebug = true;
6099 r_waterstate.numwaterplanes = 0;
6101 R_ResetViewRendering2D();
6103 R_Bloom_CopyHDRTexture();
6104 R_Bloom_MakeTexture();
6106 // restore the view settings
6107 r_waterstate.enabled = oldwaterstate;
6108 r_refdef.view.width = oldwidth;
6109 r_refdef.view.height = oldheight;
6110 r_refdef.view.colorscale = oldcolorscale;
6112 R_ResetViewRendering3D();
6114 R_ClearScreen(r_refdef.fogenabled);
6115 if (r_timereport_active)
6116 R_TimeReport("viewclear");
6119 static void R_BlendView(void)
6121 unsigned int permutation;
6122 float uservecs[4][4];
6124 switch (vid.renderpath)
6126 case RENDERPATH_GL20:
6127 case RENDERPATH_D3D9:
6128 case RENDERPATH_D3D10:
6129 case RENDERPATH_D3D11:
6130 case RENDERPATH_SOFT:
6131 case RENDERPATH_GLES2:
6133 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6134 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6135 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6136 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6137 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6139 if (r_bloomstate.texture_screen)
6141 // make sure the buffer is available
6142 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6144 R_ResetViewRendering2D();
6145 R_Mesh_SetMainRenderTargets();
6147 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6149 // declare variables
6151 static float avgspeed;
6153 speed = VectorLength(cl.movement_velocity);
6155 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
6156 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
6158 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
6159 speed = bound(0, speed, 1);
6160 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
6162 // calculate values into a standard alpha
6163 cl.motionbluralpha = 1 - exp(-
6165 (r_motionblur.value * speed / 80)
6167 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6170 max(0.0001, cl.time - cl.oldtime) // fps independent
6173 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6174 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6176 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6178 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6179 GL_Color(1, 1, 1, cl.motionbluralpha);
6180 switch(vid.renderpath)
6182 case RENDERPATH_GL11:
6183 case RENDERPATH_GL13:
6184 case RENDERPATH_GL20:
6185 case RENDERPATH_GLES1:
6186 case RENDERPATH_GLES2:
6187 case RENDERPATH_SOFT:
6188 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6190 case RENDERPATH_D3D9:
6191 case RENDERPATH_D3D10:
6192 case RENDERPATH_D3D11:
6193 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6196 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6197 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6198 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6202 // copy view into the screen texture
6203 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);
6204 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6206 else if (!r_bloomstate.texture_bloom)
6208 // we may still have to do view tint...
6209 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6211 // apply a color tint to the whole view
6212 R_ResetViewRendering2D();
6213 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6214 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6215 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6216 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6217 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6219 break; // no screen processing, no bloom, skip it
6222 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6224 // render simple bloom effect
6225 // copy the screen and shrink it and darken it for the bloom process
6226 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6227 // make the bloom texture
6228 R_Bloom_MakeTexture();
6231 #if _MSC_VER >= 1400
6232 #define sscanf sscanf_s
6234 memset(uservecs, 0, sizeof(uservecs));
6235 if (r_glsl_postprocess_uservec1_enable.integer)
6236 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6237 if (r_glsl_postprocess_uservec2_enable.integer)
6238 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6239 if (r_glsl_postprocess_uservec3_enable.integer)
6240 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6241 if (r_glsl_postprocess_uservec4_enable.integer)
6242 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6244 R_ResetViewRendering2D();
6245 GL_Color(1, 1, 1, 1);
6246 GL_BlendFunc(GL_ONE, GL_ZERO);
6248 switch(vid.renderpath)
6250 case RENDERPATH_GL20:
6251 case RENDERPATH_GLES2:
6252 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6253 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6254 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_bloomstate.texture_screen);
6255 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_bloomstate.texture_bloom );
6256 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6257 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]);
6258 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6259 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]);
6260 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]);
6261 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]);
6262 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]);
6263 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6264 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6265 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);
6267 case RENDERPATH_D3D9:
6269 // 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...
6270 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6271 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6272 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6273 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6274 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6275 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6276 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6277 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6278 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6279 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6280 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6281 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6282 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6283 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6286 case RENDERPATH_D3D10:
6287 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6289 case RENDERPATH_D3D11:
6290 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6292 case RENDERPATH_SOFT:
6293 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6294 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6295 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6296 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6297 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6298 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6299 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6300 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6301 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6302 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6303 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6304 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6305 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6306 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6311 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6312 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6314 case RENDERPATH_GL11:
6315 case RENDERPATH_GL13:
6316 case RENDERPATH_GLES1:
6317 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6319 // apply a color tint to the whole view
6320 R_ResetViewRendering2D();
6321 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6322 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6323 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6324 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6325 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6331 matrix4x4_t r_waterscrollmatrix;
6333 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6335 if (r_refdef.fog_density)
6337 r_refdef.fogcolor[0] = r_refdef.fog_red;
6338 r_refdef.fogcolor[1] = r_refdef.fog_green;
6339 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6341 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6342 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6343 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6344 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6348 VectorCopy(r_refdef.fogcolor, fogvec);
6349 // color.rgb *= ContrastBoost * SceneBrightness;
6350 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6351 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6352 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6353 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6358 void R_UpdateVariables(void)
6362 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6364 r_refdef.farclip = r_farclip_base.value;
6365 if (r_refdef.scene.worldmodel)
6366 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6367 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6369 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6370 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6371 r_refdef.polygonfactor = 0;
6372 r_refdef.polygonoffset = 0;
6373 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6374 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6376 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6377 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6378 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6379 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6380 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6381 if (FAKELIGHT_ENABLED)
6383 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6385 if (r_showsurfaces.integer)
6387 r_refdef.scene.rtworld = false;
6388 r_refdef.scene.rtworldshadows = false;
6389 r_refdef.scene.rtdlight = false;
6390 r_refdef.scene.rtdlightshadows = false;
6391 r_refdef.lightmapintensity = 0;
6394 if (gamemode == GAME_NEHAHRA)
6396 if (gl_fogenable.integer)
6398 r_refdef.oldgl_fogenable = true;
6399 r_refdef.fog_density = gl_fogdensity.value;
6400 r_refdef.fog_red = gl_fogred.value;
6401 r_refdef.fog_green = gl_foggreen.value;
6402 r_refdef.fog_blue = gl_fogblue.value;
6403 r_refdef.fog_alpha = 1;
6404 r_refdef.fog_start = 0;
6405 r_refdef.fog_end = gl_skyclip.value;
6406 r_refdef.fog_height = 1<<30;
6407 r_refdef.fog_fadedepth = 128;
6409 else if (r_refdef.oldgl_fogenable)
6411 r_refdef.oldgl_fogenable = false;
6412 r_refdef.fog_density = 0;
6413 r_refdef.fog_red = 0;
6414 r_refdef.fog_green = 0;
6415 r_refdef.fog_blue = 0;
6416 r_refdef.fog_alpha = 0;
6417 r_refdef.fog_start = 0;
6418 r_refdef.fog_end = 0;
6419 r_refdef.fog_height = 1<<30;
6420 r_refdef.fog_fadedepth = 128;
6424 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6425 r_refdef.fog_start = max(0, r_refdef.fog_start);
6426 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6428 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6430 if (r_refdef.fog_density && r_drawfog.integer)
6432 r_refdef.fogenabled = true;
6433 // this is the point where the fog reaches 0.9986 alpha, which we
6434 // consider a good enough cutoff point for the texture
6435 // (0.9986 * 256 == 255.6)
6436 if (r_fog_exp2.integer)
6437 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6439 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6440 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6441 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6442 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6443 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6444 R_BuildFogHeightTexture();
6445 // fog color was already set
6446 // update the fog texture
6447 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)
6448 R_BuildFogTexture();
6449 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6450 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6453 r_refdef.fogenabled = false;
6455 switch(vid.renderpath)
6457 case RENDERPATH_GL20:
6458 case RENDERPATH_D3D9:
6459 case RENDERPATH_D3D10:
6460 case RENDERPATH_D3D11:
6461 case RENDERPATH_SOFT:
6462 case RENDERPATH_GLES2:
6463 if(v_glslgamma.integer && !vid_gammatables_trivial)
6465 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6467 // build GLSL gamma texture
6468 #define RAMPWIDTH 256
6469 unsigned short ramp[RAMPWIDTH * 3];
6470 unsigned char rampbgr[RAMPWIDTH][4];
6473 r_texture_gammaramps_serial = vid_gammatables_serial;
6475 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6476 for(i = 0; i < RAMPWIDTH; ++i)
6478 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6479 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6480 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6483 if (r_texture_gammaramps)
6485 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6489 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6495 // remove GLSL gamma texture
6498 case RENDERPATH_GL11:
6499 case RENDERPATH_GL13:
6500 case RENDERPATH_GLES1:
6505 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6506 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6512 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6513 if( scenetype != r_currentscenetype ) {
6514 // store the old scenetype
6515 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6516 r_currentscenetype = scenetype;
6517 // move in the new scene
6518 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6527 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6529 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6530 if( scenetype == r_currentscenetype ) {
6531 return &r_refdef.scene;
6533 return &r_scenes_store[ scenetype ];
6542 int dpsoftrast_test;
6543 void R_RenderView(void)
6545 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6547 dpsoftrast_test = r_test.integer;
6549 if (r_timereport_active)
6550 R_TimeReport("start");
6551 r_textureframe++; // used only by R_GetCurrentTexture
6552 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6554 if(R_CompileShader_CheckStaticParms())
6557 if (!r_drawentities.integer)
6558 r_refdef.scene.numentities = 0;
6560 R_AnimCache_ClearCache();
6561 R_FrameData_NewFrame();
6563 /* adjust for stereo display */
6564 if(R_Stereo_Active())
6566 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);
6567 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6570 if (r_refdef.view.isoverlay)
6572 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6573 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6574 R_TimeReport("depthclear");
6576 r_refdef.view.showdebug = false;
6578 r_waterstate.enabled = false;
6579 r_waterstate.numwaterplanes = 0;
6583 r_refdef.view.matrix = originalmatrix;
6589 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6591 r_refdef.view.matrix = originalmatrix;
6592 return; //Host_Error ("R_RenderView: NULL worldmodel");
6595 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6597 R_RenderView_UpdateViewVectors();
6599 R_Shadow_UpdateWorldLightSelection();
6601 R_Bloom_StartFrame();
6602 R_Water_StartFrame();
6605 if (r_timereport_active)
6606 R_TimeReport("viewsetup");
6608 R_ResetViewRendering3D();
6610 if (r_refdef.view.clear || r_refdef.fogenabled)
6612 R_ClearScreen(r_refdef.fogenabled);
6613 if (r_timereport_active)
6614 R_TimeReport("viewclear");
6616 r_refdef.view.clear = true;
6618 // this produces a bloom texture to be used in R_BlendView() later
6619 if (r_bloomstate.hdr)
6621 R_HDR_RenderBloomTexture();
6622 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6623 r_textureframe++; // used only by R_GetCurrentTexture
6626 r_refdef.view.showdebug = true;
6629 if (r_timereport_active)
6630 R_TimeReport("visibility");
6632 r_waterstate.numwaterplanes = 0;
6633 if (r_waterstate.enabled)
6634 R_RenderWaterPlanes();
6637 r_waterstate.numwaterplanes = 0;
6640 if (r_timereport_active)
6641 R_TimeReport("blendview");
6643 GL_Scissor(0, 0, vid.width, vid.height);
6644 GL_ScissorTest(false);
6646 r_refdef.view.matrix = originalmatrix;
6651 void R_RenderWaterPlanes(void)
6653 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6655 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6656 if (r_timereport_active)
6657 R_TimeReport("waterworld");
6660 // don't let sound skip if going slow
6661 if (r_refdef.scene.extraupdate)
6664 R_DrawModelsAddWaterPlanes();
6665 if (r_timereport_active)
6666 R_TimeReport("watermodels");
6668 if (r_waterstate.numwaterplanes)
6670 R_Water_ProcessPlanes();
6671 if (r_timereport_active)
6672 R_TimeReport("waterscenes");
6676 extern void R_DrawLightningBeams (void);
6677 extern void VM_CL_AddPolygonsToMeshQueue (void);
6678 extern void R_DrawPortals (void);
6679 extern cvar_t cl_locs_show;
6680 static void R_DrawLocs(void);
6681 static void R_DrawEntityBBoxes(void);
6682 static void R_DrawModelDecals(void);
6683 extern void R_DrawModelShadows(void);
6684 extern void R_DrawModelShadowMaps(void);
6685 extern cvar_t cl_decals_newsystem;
6686 extern qboolean r_shadow_usingdeferredprepass;
6687 void R_RenderScene(void)
6689 qboolean shadowmapping = false;
6691 if (r_timereport_active)
6692 R_TimeReport("beginscene");
6694 r_refdef.stats.renders++;
6698 // don't let sound skip if going slow
6699 if (r_refdef.scene.extraupdate)
6702 R_MeshQueue_BeginScene();
6706 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);
6708 if (r_timereport_active)
6709 R_TimeReport("skystartframe");
6711 if (cl.csqc_vidvars.drawworld)
6713 // don't let sound skip if going slow
6714 if (r_refdef.scene.extraupdate)
6717 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6719 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6720 if (r_timereport_active)
6721 R_TimeReport("worldsky");
6724 if (R_DrawBrushModelsSky() && r_timereport_active)
6725 R_TimeReport("bmodelsky");
6727 if (skyrendermasked && skyrenderlater)
6729 // we have to force off the water clipping plane while rendering sky
6733 if (r_timereport_active)
6734 R_TimeReport("sky");
6738 R_AnimCache_CacheVisibleEntities();
6739 if (r_timereport_active)
6740 R_TimeReport("animation");
6742 R_Shadow_PrepareLights();
6743 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6744 R_Shadow_PrepareModelShadows();
6745 if (r_timereport_active)
6746 R_TimeReport("preparelights");
6748 if (R_Shadow_ShadowMappingEnabled())
6749 shadowmapping = true;
6751 if (r_shadow_usingdeferredprepass)
6752 R_Shadow_DrawPrepass();
6754 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6756 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6757 if (r_timereport_active)
6758 R_TimeReport("worlddepth");
6760 if (r_depthfirst.integer >= 2)
6762 R_DrawModelsDepth();
6763 if (r_timereport_active)
6764 R_TimeReport("modeldepth");
6767 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6769 R_DrawModelShadowMaps();
6770 R_ResetViewRendering3D();
6771 // don't let sound skip if going slow
6772 if (r_refdef.scene.extraupdate)
6776 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6778 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6779 if (r_timereport_active)
6780 R_TimeReport("world");
6783 // don't let sound skip if going slow
6784 if (r_refdef.scene.extraupdate)
6788 if (r_timereport_active)
6789 R_TimeReport("models");
6791 // don't let sound skip if going slow
6792 if (r_refdef.scene.extraupdate)
6795 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6797 R_DrawModelShadows();
6798 R_ResetViewRendering3D();
6799 // don't let sound skip if going slow
6800 if (r_refdef.scene.extraupdate)
6804 if (!r_shadow_usingdeferredprepass)
6806 R_Shadow_DrawLights();
6807 if (r_timereport_active)
6808 R_TimeReport("rtlights");
6811 // don't let sound skip if going slow
6812 if (r_refdef.scene.extraupdate)
6815 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6817 R_DrawModelShadows();
6818 R_ResetViewRendering3D();
6819 // don't let sound skip if going slow
6820 if (r_refdef.scene.extraupdate)
6824 if (cl.csqc_vidvars.drawworld)
6826 if (cl_decals_newsystem.integer)
6828 R_DrawModelDecals();
6829 if (r_timereport_active)
6830 R_TimeReport("modeldecals");
6835 if (r_timereport_active)
6836 R_TimeReport("decals");
6840 if (r_timereport_active)
6841 R_TimeReport("particles");
6844 if (r_timereport_active)
6845 R_TimeReport("explosions");
6847 R_DrawLightningBeams();
6848 if (r_timereport_active)
6849 R_TimeReport("lightning");
6852 VM_CL_AddPolygonsToMeshQueue();
6854 if (r_refdef.view.showdebug)
6856 if (cl_locs_show.integer)
6859 if (r_timereport_active)
6860 R_TimeReport("showlocs");
6863 if (r_drawportals.integer)
6866 if (r_timereport_active)
6867 R_TimeReport("portals");
6870 if (r_showbboxes.value > 0)
6872 R_DrawEntityBBoxes();
6873 if (r_timereport_active)
6874 R_TimeReport("bboxes");
6878 if (r_transparent.integer)
6880 R_MeshQueue_RenderTransparent();
6881 if (r_timereport_active)
6882 R_TimeReport("drawtrans");
6885 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))
6887 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6888 if (r_timereport_active)
6889 R_TimeReport("worlddebug");
6890 R_DrawModelsDebug();
6891 if (r_timereport_active)
6892 R_TimeReport("modeldebug");
6895 if (cl.csqc_vidvars.drawworld)
6897 R_Shadow_DrawCoronas();
6898 if (r_timereport_active)
6899 R_TimeReport("coronas");
6904 GL_DepthTest(false);
6905 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6906 GL_Color(1, 1, 1, 1);
6907 qglBegin(GL_POLYGON);
6908 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6909 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6910 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6911 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
6913 qglBegin(GL_POLYGON);
6914 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]);
6915 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]);
6916 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]);
6917 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]);
6919 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
6923 // don't let sound skip if going slow
6924 if (r_refdef.scene.extraupdate)
6927 R_ResetViewRendering2D();
6930 static const unsigned short bboxelements[36] =
6940 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6943 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
6945 RSurf_ActiveWorldEntity();
6947 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6948 GL_DepthMask(false);
6949 GL_DepthRange(0, 1);
6950 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6951 // R_Mesh_ResetTextureState();
6953 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
6954 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
6955 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
6956 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
6957 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
6958 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
6959 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
6960 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
6961 R_FillColors(color4f, 8, cr, cg, cb, ca);
6962 if (r_refdef.fogenabled)
6964 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
6966 f1 = RSurf_FogVertex(v);
6968 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6969 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6970 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6973 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
6974 R_Mesh_ResetTextureState();
6975 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6976 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
6979 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6983 prvm_edict_t *edict;
6984 prvm_prog_t *prog_save = prog;
6986 // this function draws bounding boxes of server entities
6990 GL_CullFace(GL_NONE);
6991 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6995 for (i = 0;i < numsurfaces;i++)
6997 edict = PRVM_EDICT_NUM(surfacelist[i]);
6998 switch ((int)edict->fields.server->solid)
7000 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
7001 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
7002 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
7003 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7004 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
7005 default: Vector4Set(color, 0, 0, 0, 0.50);break;
7007 color[3] *= r_showbboxes.value;
7008 color[3] = bound(0, color[3], 1);
7009 GL_DepthTest(!r_showdisabledepthtest.integer);
7010 GL_CullFace(r_refdef.view.cullface_front);
7011 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7017 static void R_DrawEntityBBoxes(void)
7020 prvm_edict_t *edict;
7022 prvm_prog_t *prog_save = prog;
7024 // this function draws bounding boxes of server entities
7030 for (i = 0;i < prog->num_edicts;i++)
7032 edict = PRVM_EDICT_NUM(i);
7033 if (edict->priv.server->free)
7035 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7036 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7038 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7040 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7041 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7047 static const int nomodelelement3i[24] =
7059 static const unsigned short nomodelelement3s[24] =
7071 static const float nomodelvertex3f[6*3] =
7081 static const float nomodelcolor4f[6*4] =
7083 0.0f, 0.0f, 0.5f, 1.0f,
7084 0.0f, 0.0f, 0.5f, 1.0f,
7085 0.0f, 0.5f, 0.0f, 1.0f,
7086 0.0f, 0.5f, 0.0f, 1.0f,
7087 0.5f, 0.0f, 0.0f, 1.0f,
7088 0.5f, 0.0f, 0.0f, 1.0f
7091 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7097 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);
7099 // this is only called once per entity so numsurfaces is always 1, and
7100 // surfacelist is always {0}, so this code does not handle batches
7102 if (rsurface.ent_flags & RENDER_ADDITIVE)
7104 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7105 GL_DepthMask(false);
7107 else if (rsurface.colormod[3] < 1)
7109 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7110 GL_DepthMask(false);
7114 GL_BlendFunc(GL_ONE, GL_ZERO);
7117 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7118 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7119 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7120 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7121 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7122 for (i = 0, c = color4f;i < 6;i++, c += 4)
7124 c[0] *= rsurface.colormod[0];
7125 c[1] *= rsurface.colormod[1];
7126 c[2] *= rsurface.colormod[2];
7127 c[3] *= rsurface.colormod[3];
7129 if (r_refdef.fogenabled)
7131 for (i = 0, c = color4f;i < 6;i++, c += 4)
7133 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7135 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7136 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7137 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7140 // R_Mesh_ResetTextureState();
7141 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7142 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7143 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7146 void R_DrawNoModel(entity_render_t *ent)
7149 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7150 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7151 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7153 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7156 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7158 vec3_t right1, right2, diff, normal;
7160 VectorSubtract (org2, org1, normal);
7162 // calculate 'right' vector for start
7163 VectorSubtract (r_refdef.view.origin, org1, diff);
7164 CrossProduct (normal, diff, right1);
7165 VectorNormalize (right1);
7167 // calculate 'right' vector for end
7168 VectorSubtract (r_refdef.view.origin, org2, diff);
7169 CrossProduct (normal, diff, right2);
7170 VectorNormalize (right2);
7172 vert[ 0] = org1[0] + width * right1[0];
7173 vert[ 1] = org1[1] + width * right1[1];
7174 vert[ 2] = org1[2] + width * right1[2];
7175 vert[ 3] = org1[0] - width * right1[0];
7176 vert[ 4] = org1[1] - width * right1[1];
7177 vert[ 5] = org1[2] - width * right1[2];
7178 vert[ 6] = org2[0] - width * right2[0];
7179 vert[ 7] = org2[1] - width * right2[1];
7180 vert[ 8] = org2[2] - width * right2[2];
7181 vert[ 9] = org2[0] + width * right2[0];
7182 vert[10] = org2[1] + width * right2[1];
7183 vert[11] = org2[2] + width * right2[2];
7186 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)
7188 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7189 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7190 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7191 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7192 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7193 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7194 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7195 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7196 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7197 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7198 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7199 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7202 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7207 VectorSet(v, x, y, z);
7208 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7209 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7211 if (i == mesh->numvertices)
7213 if (mesh->numvertices < mesh->maxvertices)
7215 VectorCopy(v, vertex3f);
7216 mesh->numvertices++;
7218 return mesh->numvertices;
7224 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7228 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7229 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7230 e = mesh->element3i + mesh->numtriangles * 3;
7231 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7233 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7234 if (mesh->numtriangles < mesh->maxtriangles)
7239 mesh->numtriangles++;
7241 element[1] = element[2];
7245 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7249 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7250 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7251 e = mesh->element3i + mesh->numtriangles * 3;
7252 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7254 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7255 if (mesh->numtriangles < mesh->maxtriangles)
7260 mesh->numtriangles++;
7262 element[1] = element[2];
7266 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7267 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7269 int planenum, planenum2;
7272 mplane_t *plane, *plane2;
7274 double temppoints[2][256*3];
7275 // figure out how large a bounding box we need to properly compute this brush
7277 for (w = 0;w < numplanes;w++)
7278 maxdist = max(maxdist, fabs(planes[w].dist));
7279 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7280 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7281 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7285 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7286 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7288 if (planenum2 == planenum)
7290 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);
7293 if (tempnumpoints < 3)
7295 // generate elements forming a triangle fan for this polygon
7296 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7300 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)
7302 texturelayer_t *layer;
7303 layer = t->currentlayers + t->currentnumlayers++;
7305 layer->depthmask = depthmask;
7306 layer->blendfunc1 = blendfunc1;
7307 layer->blendfunc2 = blendfunc2;
7308 layer->texture = texture;
7309 layer->texmatrix = *matrix;
7310 layer->color[0] = r;
7311 layer->color[1] = g;
7312 layer->color[2] = b;
7313 layer->color[3] = a;
7316 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7318 if(parms[0] == 0 && parms[1] == 0)
7320 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7321 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7326 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7329 index = parms[2] + r_refdef.scene.time * parms[3];
7330 index -= floor(index);
7331 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7334 case Q3WAVEFUNC_NONE:
7335 case Q3WAVEFUNC_NOISE:
7336 case Q3WAVEFUNC_COUNT:
7339 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7340 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7341 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7342 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7343 case Q3WAVEFUNC_TRIANGLE:
7345 f = index - floor(index);
7356 f = parms[0] + parms[1] * f;
7357 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7358 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7362 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7367 matrix4x4_t matrix, temp;
7368 switch(tcmod->tcmod)
7372 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7373 matrix = r_waterscrollmatrix;
7375 matrix = identitymatrix;
7377 case Q3TCMOD_ENTITYTRANSLATE:
7378 // this is used in Q3 to allow the gamecode to control texcoord
7379 // scrolling on the entity, which is not supported in darkplaces yet.
7380 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7382 case Q3TCMOD_ROTATE:
7383 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7384 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
7385 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7388 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7390 case Q3TCMOD_SCROLL:
7391 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
7393 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7394 w = (int) tcmod->parms[0];
7395 h = (int) tcmod->parms[1];
7396 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
7398 idx = (int) floor(f * w * h);
7399 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7401 case Q3TCMOD_STRETCH:
7402 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7403 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7405 case Q3TCMOD_TRANSFORM:
7406 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
7407 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
7408 VectorSet(tcmat + 6, 0 , 0 , 1);
7409 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
7410 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7412 case Q3TCMOD_TURBULENT:
7413 // this is handled in the RSurf_PrepareVertices function
7414 matrix = identitymatrix;
7418 Matrix4x4_Concat(texmatrix, &matrix, &temp);
7421 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7423 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7424 char name[MAX_QPATH];
7425 skinframe_t *skinframe;
7426 unsigned char pixels[296*194];
7427 strlcpy(cache->name, skinname, sizeof(cache->name));
7428 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7429 if (developer_loading.integer)
7430 Con_Printf("loading %s\n", name);
7431 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7432 if (!skinframe || !skinframe->base)
7435 fs_offset_t filesize;
7437 f = FS_LoadFile(name, tempmempool, true, &filesize);
7440 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7441 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7445 cache->skinframe = skinframe;
7448 texture_t *R_GetCurrentTexture(texture_t *t)
7451 const entity_render_t *ent = rsurface.entity;
7452 dp_model_t *model = ent->model;
7453 q3shaderinfo_layer_tcmod_t *tcmod;
7455 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7456 return t->currentframe;
7457 t->update_lastrenderframe = r_textureframe;
7458 t->update_lastrenderentity = (void *)ent;
7460 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7461 t->camera_entity = ent->entitynumber;
7463 t->camera_entity = 0;
7465 // switch to an alternate material if this is a q1bsp animated material
7467 texture_t *texture = t;
7468 int s = rsurface.ent_skinnum;
7469 if ((unsigned int)s >= (unsigned int)model->numskins)
7471 if (model->skinscenes)
7473 if (model->skinscenes[s].framecount > 1)
7474 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7476 s = model->skinscenes[s].firstframe;
7479 t = t + s * model->num_surfaces;
7482 // use an alternate animation if the entity's frame is not 0,
7483 // and only if the texture has an alternate animation
7484 if (rsurface.ent_alttextures && t->anim_total[1])
7485 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
7487 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
7489 texture->currentframe = t;
7492 // update currentskinframe to be a qw skin or animation frame
7493 if (rsurface.ent_qwskin >= 0)
7495 i = rsurface.ent_qwskin;
7496 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7498 r_qwskincache_size = cl.maxclients;
7500 Mem_Free(r_qwskincache);
7501 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7503 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7504 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7505 t->currentskinframe = r_qwskincache[i].skinframe;
7506 if (t->currentskinframe == NULL)
7507 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7509 else if (t->numskinframes >= 2)
7510 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7511 if (t->backgroundnumskinframes >= 2)
7512 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
7514 t->currentmaterialflags = t->basematerialflags;
7515 t->currentalpha = rsurface.colormod[3];
7516 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
7517 t->currentalpha *= r_wateralpha.value;
7518 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7519 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7520 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7521 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7522 if (!(rsurface.ent_flags & RENDER_LIGHT))
7523 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7524 else if (FAKELIGHT_ENABLED)
7526 // no modellight if using fakelight for the map
7528 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7530 // pick a model lighting mode
7531 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7532 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7534 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7536 if (rsurface.ent_flags & RENDER_ADDITIVE)
7537 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7538 else if (t->currentalpha < 1)
7539 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7540 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7541 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7542 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7543 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7544 if (t->backgroundnumskinframes)
7545 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7546 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7548 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7549 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7552 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7553 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7554 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7556 // there is no tcmod
7557 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7559 t->currenttexmatrix = r_waterscrollmatrix;
7560 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7562 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7564 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7565 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7568 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7569 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7570 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7571 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7573 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7574 if (t->currentskinframe->qpixels)
7575 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7576 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7577 if (!t->basetexture)
7578 t->basetexture = r_texture_notexture;
7579 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7580 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7581 t->nmaptexture = t->currentskinframe->nmap;
7582 if (!t->nmaptexture)
7583 t->nmaptexture = r_texture_blanknormalmap;
7584 t->glosstexture = r_texture_black;
7585 t->glowtexture = t->currentskinframe->glow;
7586 t->fogtexture = t->currentskinframe->fog;
7587 t->reflectmasktexture = t->currentskinframe->reflect;
7588 if (t->backgroundnumskinframes)
7590 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7591 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7592 t->backgroundglosstexture = r_texture_black;
7593 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7594 if (!t->backgroundnmaptexture)
7595 t->backgroundnmaptexture = r_texture_blanknormalmap;
7599 t->backgroundbasetexture = r_texture_white;
7600 t->backgroundnmaptexture = r_texture_blanknormalmap;
7601 t->backgroundglosstexture = r_texture_black;
7602 t->backgroundglowtexture = NULL;
7604 t->specularpower = r_shadow_glossexponent.value;
7605 // TODO: store reference values for these in the texture?
7606 t->specularscale = 0;
7607 if (r_shadow_gloss.integer > 0)
7609 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7611 if (r_shadow_glossintensity.value > 0)
7613 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7614 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7615 t->specularscale = r_shadow_glossintensity.value;
7618 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7620 t->glosstexture = r_texture_white;
7621 t->backgroundglosstexture = r_texture_white;
7622 t->specularscale = r_shadow_gloss2intensity.value;
7623 t->specularpower = r_shadow_gloss2exponent.value;
7626 t->specularscale *= t->specularscalemod;
7627 t->specularpower *= t->specularpowermod;
7629 // lightmaps mode looks bad with dlights using actual texturing, so turn
7630 // off the colormap and glossmap, but leave the normalmap on as it still
7631 // accurately represents the shading involved
7632 if (gl_lightmaps.integer)
7634 t->basetexture = r_texture_grey128;
7635 t->pantstexture = r_texture_black;
7636 t->shirttexture = r_texture_black;
7637 t->nmaptexture = r_texture_blanknormalmap;
7638 t->glosstexture = r_texture_black;
7639 t->glowtexture = NULL;
7640 t->fogtexture = NULL;
7641 t->reflectmasktexture = NULL;
7642 t->backgroundbasetexture = NULL;
7643 t->backgroundnmaptexture = r_texture_blanknormalmap;
7644 t->backgroundglosstexture = r_texture_black;
7645 t->backgroundglowtexture = NULL;
7646 t->specularscale = 0;
7647 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7650 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7651 VectorClear(t->dlightcolor);
7652 t->currentnumlayers = 0;
7653 if (t->currentmaterialflags & MATERIALFLAG_WALL)
7655 int blendfunc1, blendfunc2;
7657 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7659 blendfunc1 = GL_SRC_ALPHA;
7660 blendfunc2 = GL_ONE;
7662 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7664 blendfunc1 = GL_SRC_ALPHA;
7665 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7667 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7669 blendfunc1 = t->customblendfunc[0];
7670 blendfunc2 = t->customblendfunc[1];
7674 blendfunc1 = GL_ONE;
7675 blendfunc2 = GL_ZERO;
7677 // don't colormod evilblend textures
7678 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7679 VectorSet(t->lightmapcolor, 1, 1, 1);
7680 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7681 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7683 // fullbright is not affected by r_refdef.lightmapintensity
7684 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]);
7685 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7686 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]);
7687 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7688 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]);
7692 vec3_t ambientcolor;
7694 // set the color tint used for lights affecting this surface
7695 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7697 // q3bsp has no lightmap updates, so the lightstylevalue that
7698 // would normally be baked into the lightmap must be
7699 // applied to the color
7700 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7701 if (model->type == mod_brushq3)
7702 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7703 colorscale *= r_refdef.lightmapintensity;
7704 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7705 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7706 // basic lit geometry
7707 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]);
7708 // add pants/shirt if needed
7709 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7710 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]);
7711 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7712 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]);
7713 // now add ambient passes if needed
7714 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7716 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]);
7717 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7718 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]);
7719 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7720 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]);
7723 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7724 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]);
7725 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7727 // if this is opaque use alpha blend which will darken the earlier
7730 // if this is an alpha blended material, all the earlier passes
7731 // were darkened by fog already, so we only need to add the fog
7732 // color ontop through the fog mask texture
7734 // if this is an additive blended material, all the earlier passes
7735 // were darkened by fog already, and we should not add fog color
7736 // (because the background was not darkened, there is no fog color
7737 // that was lost behind it).
7738 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]);
7742 return t->currentframe;
7745 rsurfacestate_t rsurface;
7747 void RSurf_ActiveWorldEntity(void)
7749 dp_model_t *model = r_refdef.scene.worldmodel;
7750 //if (rsurface.entity == r_refdef.scene.worldentity)
7752 rsurface.entity = r_refdef.scene.worldentity;
7753 rsurface.skeleton = NULL;
7754 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7755 rsurface.ent_skinnum = 0;
7756 rsurface.ent_qwskin = -1;
7757 rsurface.ent_shadertime = 0;
7758 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7759 rsurface.matrix = identitymatrix;
7760 rsurface.inversematrix = identitymatrix;
7761 rsurface.matrixscale = 1;
7762 rsurface.inversematrixscale = 1;
7763 R_EntityMatrix(&identitymatrix);
7764 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7765 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7766 rsurface.fograngerecip = r_refdef.fograngerecip;
7767 rsurface.fogheightfade = r_refdef.fogheightfade;
7768 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7769 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7770 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7771 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7772 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7773 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7774 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7775 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7776 rsurface.colormod[3] = 1;
7777 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);
7778 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7779 rsurface.frameblend[0].lerp = 1;
7780 rsurface.ent_alttextures = false;
7781 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7782 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7783 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7784 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7785 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7786 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7787 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7788 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7789 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7790 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7791 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7792 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7793 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7794 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7795 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7796 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7797 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7798 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7799 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7800 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7801 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7802 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7803 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7804 rsurface.modelelement3i = model->surfmesh.data_element3i;
7805 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7806 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7807 rsurface.modelelement3s = model->surfmesh.data_element3s;
7808 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7809 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7810 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7811 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7812 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7813 rsurface.modelsurfaces = model->data_surfaces;
7814 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7815 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7816 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7817 rsurface.modelgeneratedvertex = false;
7818 rsurface.batchgeneratedvertex = false;
7819 rsurface.batchfirstvertex = 0;
7820 rsurface.batchnumvertices = 0;
7821 rsurface.batchfirsttriangle = 0;
7822 rsurface.batchnumtriangles = 0;
7823 rsurface.batchvertex3f = NULL;
7824 rsurface.batchvertex3f_vertexbuffer = NULL;
7825 rsurface.batchvertex3f_bufferoffset = 0;
7826 rsurface.batchsvector3f = NULL;
7827 rsurface.batchsvector3f_vertexbuffer = NULL;
7828 rsurface.batchsvector3f_bufferoffset = 0;
7829 rsurface.batchtvector3f = NULL;
7830 rsurface.batchtvector3f_vertexbuffer = NULL;
7831 rsurface.batchtvector3f_bufferoffset = 0;
7832 rsurface.batchnormal3f = NULL;
7833 rsurface.batchnormal3f_vertexbuffer = NULL;
7834 rsurface.batchnormal3f_bufferoffset = 0;
7835 rsurface.batchlightmapcolor4f = NULL;
7836 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7837 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7838 rsurface.batchtexcoordtexture2f = NULL;
7839 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7840 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7841 rsurface.batchtexcoordlightmap2f = NULL;
7842 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7843 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7844 rsurface.batchvertexmesh = NULL;
7845 rsurface.batchvertexmeshbuffer = NULL;
7846 rsurface.batchvertex3fbuffer = NULL;
7847 rsurface.batchelement3i = NULL;
7848 rsurface.batchelement3i_indexbuffer = NULL;
7849 rsurface.batchelement3i_bufferoffset = 0;
7850 rsurface.batchelement3s = NULL;
7851 rsurface.batchelement3s_indexbuffer = NULL;
7852 rsurface.batchelement3s_bufferoffset = 0;
7853 rsurface.passcolor4f = NULL;
7854 rsurface.passcolor4f_vertexbuffer = NULL;
7855 rsurface.passcolor4f_bufferoffset = 0;
7858 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7860 dp_model_t *model = ent->model;
7861 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7863 rsurface.entity = (entity_render_t *)ent;
7864 rsurface.skeleton = ent->skeleton;
7865 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7866 rsurface.ent_skinnum = ent->skinnum;
7867 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;
7868 rsurface.ent_shadertime = ent->shadertime;
7869 rsurface.ent_flags = ent->flags;
7870 rsurface.matrix = ent->matrix;
7871 rsurface.inversematrix = ent->inversematrix;
7872 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7873 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7874 R_EntityMatrix(&rsurface.matrix);
7875 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7876 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7877 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7878 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7879 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7880 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7881 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7882 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7883 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7884 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7885 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7886 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7887 rsurface.colormod[3] = ent->alpha;
7888 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7889 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7890 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7891 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7892 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7893 if (ent->model->brush.submodel && !prepass)
7895 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7896 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7898 if (model->surfmesh.isanimated && model->AnimateVertices)
7900 if (ent->animcache_vertex3f)
7902 rsurface.modelvertex3f = ent->animcache_vertex3f;
7903 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7904 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7905 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7906 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7907 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
7908 rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
7910 else if (wanttangents)
7912 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7913 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7914 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7915 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7916 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7917 rsurface.modelvertexmesh = NULL;
7918 rsurface.modelvertexmeshbuffer = NULL;
7919 rsurface.modelvertex3fbuffer = NULL;
7921 else if (wantnormals)
7923 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7924 rsurface.modelsvector3f = NULL;
7925 rsurface.modeltvector3f = NULL;
7926 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7927 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
7928 rsurface.modelvertexmesh = NULL;
7929 rsurface.modelvertexmeshbuffer = NULL;
7930 rsurface.modelvertex3fbuffer = NULL;
7934 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7935 rsurface.modelsvector3f = NULL;
7936 rsurface.modeltvector3f = NULL;
7937 rsurface.modelnormal3f = NULL;
7938 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
7939 rsurface.modelvertexmesh = NULL;
7940 rsurface.modelvertexmeshbuffer = NULL;
7941 rsurface.modelvertex3fbuffer = NULL;
7943 rsurface.modelvertex3f_vertexbuffer = 0;
7944 rsurface.modelvertex3f_bufferoffset = 0;
7945 rsurface.modelsvector3f_vertexbuffer = 0;
7946 rsurface.modelsvector3f_bufferoffset = 0;
7947 rsurface.modeltvector3f_vertexbuffer = 0;
7948 rsurface.modeltvector3f_bufferoffset = 0;
7949 rsurface.modelnormal3f_vertexbuffer = 0;
7950 rsurface.modelnormal3f_bufferoffset = 0;
7951 rsurface.modelgeneratedvertex = true;
7955 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7956 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7957 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7958 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7959 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7960 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7961 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7962 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7963 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7964 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7965 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7966 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7967 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7968 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7969 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7970 rsurface.modelgeneratedvertex = false;
7972 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7973 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7974 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7975 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7976 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7977 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7978 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7979 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7980 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7981 rsurface.modelelement3i = model->surfmesh.data_element3i;
7982 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7983 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7984 rsurface.modelelement3s = model->surfmesh.data_element3s;
7985 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7986 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7987 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7988 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7989 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7990 rsurface.modelsurfaces = model->data_surfaces;
7991 rsurface.batchgeneratedvertex = false;
7992 rsurface.batchfirstvertex = 0;
7993 rsurface.batchnumvertices = 0;
7994 rsurface.batchfirsttriangle = 0;
7995 rsurface.batchnumtriangles = 0;
7996 rsurface.batchvertex3f = NULL;
7997 rsurface.batchvertex3f_vertexbuffer = NULL;
7998 rsurface.batchvertex3f_bufferoffset = 0;
7999 rsurface.batchsvector3f = NULL;
8000 rsurface.batchsvector3f_vertexbuffer = NULL;
8001 rsurface.batchsvector3f_bufferoffset = 0;
8002 rsurface.batchtvector3f = NULL;
8003 rsurface.batchtvector3f_vertexbuffer = NULL;
8004 rsurface.batchtvector3f_bufferoffset = 0;
8005 rsurface.batchnormal3f = NULL;
8006 rsurface.batchnormal3f_vertexbuffer = NULL;
8007 rsurface.batchnormal3f_bufferoffset = 0;
8008 rsurface.batchlightmapcolor4f = NULL;
8009 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8010 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8011 rsurface.batchtexcoordtexture2f = NULL;
8012 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8013 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8014 rsurface.batchtexcoordlightmap2f = NULL;
8015 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8016 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8017 rsurface.batchvertexmesh = NULL;
8018 rsurface.batchvertexmeshbuffer = NULL;
8019 rsurface.batchvertex3fbuffer = NULL;
8020 rsurface.batchelement3i = NULL;
8021 rsurface.batchelement3i_indexbuffer = NULL;
8022 rsurface.batchelement3i_bufferoffset = 0;
8023 rsurface.batchelement3s = NULL;
8024 rsurface.batchelement3s_indexbuffer = NULL;
8025 rsurface.batchelement3s_bufferoffset = 0;
8026 rsurface.passcolor4f = NULL;
8027 rsurface.passcolor4f_vertexbuffer = NULL;
8028 rsurface.passcolor4f_bufferoffset = 0;
8031 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)
8033 rsurface.entity = r_refdef.scene.worldentity;
8034 rsurface.skeleton = NULL;
8035 rsurface.ent_skinnum = 0;
8036 rsurface.ent_qwskin = -1;
8037 rsurface.ent_shadertime = shadertime;
8038 rsurface.ent_flags = entflags;
8039 rsurface.modelnumvertices = numvertices;
8040 rsurface.modelnumtriangles = numtriangles;
8041 rsurface.matrix = *matrix;
8042 rsurface.inversematrix = *inversematrix;
8043 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8044 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8045 R_EntityMatrix(&rsurface.matrix);
8046 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8047 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8048 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8049 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8050 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8051 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8052 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8053 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8054 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8055 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8056 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8057 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8058 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);
8059 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8060 rsurface.frameblend[0].lerp = 1;
8061 rsurface.ent_alttextures = false;
8062 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8063 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8066 rsurface.modelvertex3f = (float *)vertex3f;
8067 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8068 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8069 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8071 else if (wantnormals)
8073 rsurface.modelvertex3f = (float *)vertex3f;
8074 rsurface.modelsvector3f = NULL;
8075 rsurface.modeltvector3f = NULL;
8076 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8080 rsurface.modelvertex3f = (float *)vertex3f;
8081 rsurface.modelsvector3f = NULL;
8082 rsurface.modeltvector3f = NULL;
8083 rsurface.modelnormal3f = NULL;
8085 rsurface.modelvertexmesh = NULL;
8086 rsurface.modelvertexmeshbuffer = NULL;
8087 rsurface.modelvertex3fbuffer = NULL;
8088 rsurface.modelvertex3f_vertexbuffer = 0;
8089 rsurface.modelvertex3f_bufferoffset = 0;
8090 rsurface.modelsvector3f_vertexbuffer = 0;
8091 rsurface.modelsvector3f_bufferoffset = 0;
8092 rsurface.modeltvector3f_vertexbuffer = 0;
8093 rsurface.modeltvector3f_bufferoffset = 0;
8094 rsurface.modelnormal3f_vertexbuffer = 0;
8095 rsurface.modelnormal3f_bufferoffset = 0;
8096 rsurface.modelgeneratedvertex = true;
8097 rsurface.modellightmapcolor4f = (float *)color4f;
8098 rsurface.modellightmapcolor4f_vertexbuffer = 0;
8099 rsurface.modellightmapcolor4f_bufferoffset = 0;
8100 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
8101 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8102 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8103 rsurface.modeltexcoordlightmap2f = NULL;
8104 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8105 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8106 rsurface.modelelement3i = (int *)element3i;
8107 rsurface.modelelement3i_indexbuffer = NULL;
8108 rsurface.modelelement3i_bufferoffset = 0;
8109 rsurface.modelelement3s = (unsigned short *)element3s;
8110 rsurface.modelelement3s_indexbuffer = NULL;
8111 rsurface.modelelement3s_bufferoffset = 0;
8112 rsurface.modellightmapoffsets = NULL;
8113 rsurface.modelsurfaces = NULL;
8114 rsurface.batchgeneratedvertex = false;
8115 rsurface.batchfirstvertex = 0;
8116 rsurface.batchnumvertices = 0;
8117 rsurface.batchfirsttriangle = 0;
8118 rsurface.batchnumtriangles = 0;
8119 rsurface.batchvertex3f = NULL;
8120 rsurface.batchvertex3f_vertexbuffer = NULL;
8121 rsurface.batchvertex3f_bufferoffset = 0;
8122 rsurface.batchsvector3f = NULL;
8123 rsurface.batchsvector3f_vertexbuffer = NULL;
8124 rsurface.batchsvector3f_bufferoffset = 0;
8125 rsurface.batchtvector3f = NULL;
8126 rsurface.batchtvector3f_vertexbuffer = NULL;
8127 rsurface.batchtvector3f_bufferoffset = 0;
8128 rsurface.batchnormal3f = NULL;
8129 rsurface.batchnormal3f_vertexbuffer = NULL;
8130 rsurface.batchnormal3f_bufferoffset = 0;
8131 rsurface.batchlightmapcolor4f = NULL;
8132 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8133 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8134 rsurface.batchtexcoordtexture2f = NULL;
8135 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8136 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8137 rsurface.batchtexcoordlightmap2f = NULL;
8138 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8139 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8140 rsurface.batchvertexmesh = NULL;
8141 rsurface.batchvertexmeshbuffer = NULL;
8142 rsurface.batchvertex3fbuffer = NULL;
8143 rsurface.batchelement3i = NULL;
8144 rsurface.batchelement3i_indexbuffer = NULL;
8145 rsurface.batchelement3i_bufferoffset = 0;
8146 rsurface.batchelement3s = NULL;
8147 rsurface.batchelement3s_indexbuffer = NULL;
8148 rsurface.batchelement3s_bufferoffset = 0;
8149 rsurface.passcolor4f = NULL;
8150 rsurface.passcolor4f_vertexbuffer = NULL;
8151 rsurface.passcolor4f_bufferoffset = 0;
8153 if (rsurface.modelnumvertices && rsurface.modelelement3i)
8155 if ((wantnormals || wanttangents) && !normal3f)
8157 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8158 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8160 if (wanttangents && !svector3f)
8162 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8163 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8164 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8169 float RSurf_FogPoint(const float *v)
8171 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8172 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8173 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8174 float FogHeightFade = r_refdef.fogheightfade;
8176 unsigned int fogmasktableindex;
8177 if (r_refdef.fogplaneviewabove)
8178 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8180 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8181 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8182 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8185 float RSurf_FogVertex(const float *v)
8187 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8188 float FogPlaneViewDist = rsurface.fogplaneviewdist;
8189 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8190 float FogHeightFade = rsurface.fogheightfade;
8192 unsigned int fogmasktableindex;
8193 if (r_refdef.fogplaneviewabove)
8194 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8196 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8197 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8198 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8201 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8204 for (i = 0;i < numelements;i++)
8205 outelement3i[i] = inelement3i[i] + adjust;
8208 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8209 extern cvar_t gl_vbo;
8210 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8218 int surfacefirsttriangle;
8219 int surfacenumtriangles;
8220 int surfacefirstvertex;
8221 int surfaceendvertex;
8222 int surfacenumvertices;
8223 int batchnumvertices;
8224 int batchnumtriangles;
8228 qboolean dynamicvertex;
8232 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8234 q3shaderinfo_deform_t *deform;
8235 const msurface_t *surface, *firstsurface;
8236 r_vertexmesh_t *vertexmesh;
8237 if (!texturenumsurfaces)
8239 // find vertex range of this surface batch
8241 firstsurface = texturesurfacelist[0];
8242 firsttriangle = firstsurface->num_firsttriangle;
8243 batchnumvertices = 0;
8244 batchnumtriangles = 0;
8245 firstvertex = endvertex = firstsurface->num_firstvertex;
8246 for (i = 0;i < texturenumsurfaces;i++)
8248 surface = texturesurfacelist[i];
8249 if (surface != firstsurface + i)
8251 surfacefirstvertex = surface->num_firstvertex;
8252 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8253 surfacenumvertices = surface->num_vertices;
8254 surfacenumtriangles = surface->num_triangles;
8255 if (firstvertex > surfacefirstvertex)
8256 firstvertex = surfacefirstvertex;
8257 if (endvertex < surfaceendvertex)
8258 endvertex = surfaceendvertex;
8259 batchnumvertices += surfacenumvertices;
8260 batchnumtriangles += surfacenumtriangles;
8263 // we now know the vertex range used, and if there are any gaps in it
8264 rsurface.batchfirstvertex = firstvertex;
8265 rsurface.batchnumvertices = endvertex - firstvertex;
8266 rsurface.batchfirsttriangle = firsttriangle;
8267 rsurface.batchnumtriangles = batchnumtriangles;
8269 // this variable holds flags for which properties have been updated that
8270 // may require regenerating vertexmesh array...
8273 // check if any dynamic vertex processing must occur
8274 dynamicvertex = false;
8276 // if there is a chance of animated vertex colors, it's a dynamic batch
8277 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8279 dynamicvertex = true;
8280 batchneed |= BATCHNEED_NOGAPS;
8281 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8284 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8286 switch (deform->deform)
8289 case Q3DEFORM_PROJECTIONSHADOW:
8290 case Q3DEFORM_TEXT0:
8291 case Q3DEFORM_TEXT1:
8292 case Q3DEFORM_TEXT2:
8293 case Q3DEFORM_TEXT3:
8294 case Q3DEFORM_TEXT4:
8295 case Q3DEFORM_TEXT5:
8296 case Q3DEFORM_TEXT6:
8297 case Q3DEFORM_TEXT7:
8300 case Q3DEFORM_AUTOSPRITE:
8301 dynamicvertex = true;
8302 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8303 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8305 case Q3DEFORM_AUTOSPRITE2:
8306 dynamicvertex = true;
8307 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8308 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8310 case Q3DEFORM_NORMAL:
8311 dynamicvertex = true;
8312 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8313 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8316 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8317 break; // if wavefunc is a nop, ignore this transform
8318 dynamicvertex = true;
8319 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8320 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8322 case Q3DEFORM_BULGE:
8323 dynamicvertex = true;
8324 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8325 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8328 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8329 break; // if wavefunc is a nop, ignore this transform
8330 dynamicvertex = true;
8331 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8332 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8336 switch(rsurface.texture->tcgen.tcgen)
8339 case Q3TCGEN_TEXTURE:
8341 case Q3TCGEN_LIGHTMAP:
8342 dynamicvertex = true;
8343 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8344 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8346 case Q3TCGEN_VECTOR:
8347 dynamicvertex = true;
8348 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8349 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8351 case Q3TCGEN_ENVIRONMENT:
8352 dynamicvertex = true;
8353 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8354 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8357 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8359 dynamicvertex = true;
8360 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8361 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8364 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8366 dynamicvertex = true;
8367 batchneed |= BATCHNEED_NOGAPS;
8368 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8371 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8373 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8374 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
8375 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
8376 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
8377 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8378 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8379 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8382 // when the model data has no vertex buffer (dynamic mesh), we need to
8384 if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8385 batchneed |= BATCHNEED_NOGAPS;
8387 // if needsupdate, we have to do a dynamic vertex batch for sure
8388 if (needsupdate & batchneed)
8389 dynamicvertex = true;
8391 // see if we need to build vertexmesh from arrays
8392 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8393 dynamicvertex = true;
8395 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8396 // also some drivers strongly dislike firstvertex
8397 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8398 dynamicvertex = true;
8400 rsurface.batchvertex3f = rsurface.modelvertex3f;
8401 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8402 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8403 rsurface.batchsvector3f = rsurface.modelsvector3f;
8404 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8405 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8406 rsurface.batchtvector3f = rsurface.modeltvector3f;
8407 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8408 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8409 rsurface.batchnormal3f = rsurface.modelnormal3f;
8410 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8411 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8412 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8413 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
8414 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8415 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8416 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
8417 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
8418 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8419 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8420 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8421 rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8422 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8423 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8424 rsurface.batchelement3i = rsurface.modelelement3i;
8425 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8426 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8427 rsurface.batchelement3s = rsurface.modelelement3s;
8428 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8429 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8431 // if any dynamic vertex processing has to occur in software, we copy the
8432 // entire surface list together before processing to rebase the vertices
8433 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8435 // if any gaps exist and we do not have a static vertex buffer, we have to
8436 // copy the surface list together to avoid wasting upload bandwidth on the
8437 // vertices in the gaps.
8439 // if gaps exist and we have a static vertex buffer, we still have to
8440 // combine the index buffer ranges into one dynamic index buffer.
8442 // in all cases we end up with data that can be drawn in one call.
8446 // static vertex data, just set pointers...
8447 rsurface.batchgeneratedvertex = false;
8448 // if there are gaps, we want to build a combined index buffer,
8449 // otherwise use the original static buffer with an appropriate offset
8452 // build a new triangle elements array for this batch
8453 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8454 rsurface.batchfirsttriangle = 0;
8456 for (i = 0;i < texturenumsurfaces;i++)
8458 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8459 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8460 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8461 numtriangles += surfacenumtriangles;
8463 rsurface.batchelement3i_indexbuffer = NULL;
8464 rsurface.batchelement3i_bufferoffset = 0;
8465 rsurface.batchelement3s = NULL;
8466 rsurface.batchelement3s_indexbuffer = NULL;
8467 rsurface.batchelement3s_bufferoffset = 0;
8468 if (endvertex <= 65536)
8470 // make a 16bit (unsigned short) index array if possible
8471 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8472 for (i = 0;i < numtriangles*3;i++)
8473 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8479 // something needs software processing, do it for real...
8480 // we only directly handle separate array data in this case and then
8481 // generate interleaved data if needed...
8482 rsurface.batchgeneratedvertex = true;
8484 // now copy the vertex data into a combined array and make an index array
8485 // (this is what Quake3 does all the time)
8486 //if (gaps || rsurface.batchfirstvertex)
8488 rsurface.batchvertex3fbuffer = NULL;
8489 rsurface.batchvertexmesh = NULL;
8490 rsurface.batchvertexmeshbuffer = NULL;
8491 rsurface.batchvertex3f = NULL;
8492 rsurface.batchvertex3f_vertexbuffer = NULL;
8493 rsurface.batchvertex3f_bufferoffset = 0;
8494 rsurface.batchsvector3f = NULL;
8495 rsurface.batchsvector3f_vertexbuffer = NULL;
8496 rsurface.batchsvector3f_bufferoffset = 0;
8497 rsurface.batchtvector3f = NULL;
8498 rsurface.batchtvector3f_vertexbuffer = NULL;
8499 rsurface.batchtvector3f_bufferoffset = 0;
8500 rsurface.batchnormal3f = NULL;
8501 rsurface.batchnormal3f_vertexbuffer = NULL;
8502 rsurface.batchnormal3f_bufferoffset = 0;
8503 rsurface.batchlightmapcolor4f = NULL;
8504 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8505 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8506 rsurface.batchtexcoordtexture2f = NULL;
8507 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8508 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8509 rsurface.batchtexcoordlightmap2f = NULL;
8510 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8511 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8512 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8513 rsurface.batchelement3i_indexbuffer = NULL;
8514 rsurface.batchelement3i_bufferoffset = 0;
8515 rsurface.batchelement3s = NULL;
8516 rsurface.batchelement3s_indexbuffer = NULL;
8517 rsurface.batchelement3s_bufferoffset = 0;
8518 // we'll only be setting up certain arrays as needed
8519 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8520 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8521 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8522 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8523 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8524 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8525 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8527 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8528 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8530 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8531 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8532 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8533 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8534 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8535 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8538 for (i = 0;i < texturenumsurfaces;i++)
8540 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8541 surfacenumvertices = texturesurfacelist[i]->num_vertices;
8542 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8543 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8544 // copy only the data requested
8545 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8546 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8547 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8549 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8550 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8551 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
8552 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8553 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
8555 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8556 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8558 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
8559 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8560 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
8561 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8562 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
8563 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8565 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8566 numvertices += surfacenumvertices;
8567 numtriangles += surfacenumtriangles;
8570 // generate a 16bit index array as well if possible
8571 // (in general, dynamic batches fit)
8572 if (numvertices <= 65536)
8574 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8575 for (i = 0;i < numtriangles*3;i++)
8576 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8579 // since we've copied everything, the batch now starts at 0
8580 rsurface.batchfirstvertex = 0;
8581 rsurface.batchnumvertices = batchnumvertices;
8582 rsurface.batchfirsttriangle = 0;
8583 rsurface.batchnumtriangles = batchnumtriangles;
8586 // q1bsp surfaces rendered in vertex color mode have to have colors
8587 // calculated based on lightstyles
8588 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8590 // generate color arrays for the surfaces in this list
8595 const unsigned char *lm;
8596 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8597 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8598 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8600 for (i = 0;i < texturenumsurfaces;i++)
8602 surface = texturesurfacelist[i];
8603 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8604 surfacenumvertices = surface->num_vertices;
8605 if (surface->lightmapinfo->samples)
8607 for (j = 0;j < surfacenumvertices;j++)
8609 lm = surface->lightmapinfo->samples + offsets[j];
8610 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8611 VectorScale(lm, scale, c);
8612 if (surface->lightmapinfo->styles[1] != 255)
8614 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8616 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8617 VectorMA(c, scale, lm, c);
8618 if (surface->lightmapinfo->styles[2] != 255)
8621 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8622 VectorMA(c, scale, lm, c);
8623 if (surface->lightmapinfo->styles[3] != 255)
8626 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8627 VectorMA(c, scale, lm, c);
8634 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);
8640 for (j = 0;j < surfacenumvertices;j++)
8642 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8649 // if vertices are deformed (sprite flares and things in maps, possibly
8650 // water waves, bulges and other deformations), modify the copied vertices
8652 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8654 switch (deform->deform)
8657 case Q3DEFORM_PROJECTIONSHADOW:
8658 case Q3DEFORM_TEXT0:
8659 case Q3DEFORM_TEXT1:
8660 case Q3DEFORM_TEXT2:
8661 case Q3DEFORM_TEXT3:
8662 case Q3DEFORM_TEXT4:
8663 case Q3DEFORM_TEXT5:
8664 case Q3DEFORM_TEXT6:
8665 case Q3DEFORM_TEXT7:
8668 case Q3DEFORM_AUTOSPRITE:
8669 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8670 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8671 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8672 VectorNormalize(newforward);
8673 VectorNormalize(newright);
8674 VectorNormalize(newup);
8675 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8676 // rsurface.batchvertex3f_vertexbuffer = NULL;
8677 // rsurface.batchvertex3f_bufferoffset = 0;
8678 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8679 // rsurface.batchsvector3f_vertexbuffer = NULL;
8680 // rsurface.batchsvector3f_bufferoffset = 0;
8681 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8682 // rsurface.batchtvector3f_vertexbuffer = NULL;
8683 // rsurface.batchtvector3f_bufferoffset = 0;
8684 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8685 // rsurface.batchnormal3f_vertexbuffer = NULL;
8686 // rsurface.batchnormal3f_bufferoffset = 0;
8687 // a single autosprite surface can contain multiple sprites...
8688 for (j = 0;j < batchnumvertices - 3;j += 4)
8690 VectorClear(center);
8691 for (i = 0;i < 4;i++)
8692 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8693 VectorScale(center, 0.25f, center);
8694 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8695 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8696 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8697 for (i = 0;i < 4;i++)
8699 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8700 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8703 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8704 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8705 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);
8707 case Q3DEFORM_AUTOSPRITE2:
8708 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8709 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8710 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8711 VectorNormalize(newforward);
8712 VectorNormalize(newright);
8713 VectorNormalize(newup);
8714 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8715 // rsurface.batchvertex3f_vertexbuffer = NULL;
8716 // rsurface.batchvertex3f_bufferoffset = 0;
8718 const float *v1, *v2;
8728 memset(shortest, 0, sizeof(shortest));
8729 // a single autosprite surface can contain multiple sprites...
8730 for (j = 0;j < batchnumvertices - 3;j += 4)
8732 VectorClear(center);
8733 for (i = 0;i < 4;i++)
8734 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8735 VectorScale(center, 0.25f, center);
8736 // find the two shortest edges, then use them to define the
8737 // axis vectors for rotating around the central axis
8738 for (i = 0;i < 6;i++)
8740 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8741 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8742 l = VectorDistance2(v1, v2);
8743 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8745 l += (1.0f / 1024.0f);
8746 if (shortest[0].length2 > l || i == 0)
8748 shortest[1] = shortest[0];
8749 shortest[0].length2 = l;
8750 shortest[0].v1 = v1;
8751 shortest[0].v2 = v2;
8753 else if (shortest[1].length2 > l || i == 1)
8755 shortest[1].length2 = l;
8756 shortest[1].v1 = v1;
8757 shortest[1].v2 = v2;
8760 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8761 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8762 // this calculates the right vector from the shortest edge
8763 // and the up vector from the edge midpoints
8764 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8765 VectorNormalize(right);
8766 VectorSubtract(end, start, up);
8767 VectorNormalize(up);
8768 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8769 VectorSubtract(rsurface.localvieworigin, center, forward);
8770 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8771 VectorNegate(forward, forward);
8772 VectorReflect(forward, 0, up, forward);
8773 VectorNormalize(forward);
8774 CrossProduct(up, forward, newright);
8775 VectorNormalize(newright);
8776 // rotate the quad around the up axis vector, this is made
8777 // especially easy by the fact we know the quad is flat,
8778 // so we only have to subtract the center position and
8779 // measure distance along the right vector, and then
8780 // multiply that by the newright vector and add back the
8782 // we also need to subtract the old position to undo the
8783 // displacement from the center, which we do with a
8784 // DotProduct, the subtraction/addition of center is also
8785 // optimized into DotProducts here
8786 l = DotProduct(right, center);
8787 for (i = 0;i < 4;i++)
8789 v1 = rsurface.batchvertex3f + 3*(j+i);
8790 f = DotProduct(right, v1) - l;
8791 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8795 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8797 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8798 // rsurface.batchnormal3f_vertexbuffer = NULL;
8799 // rsurface.batchnormal3f_bufferoffset = 0;
8800 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8802 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8804 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8805 // rsurface.batchsvector3f_vertexbuffer = NULL;
8806 // rsurface.batchsvector3f_bufferoffset = 0;
8807 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8808 // rsurface.batchtvector3f_vertexbuffer = NULL;
8809 // rsurface.batchtvector3f_bufferoffset = 0;
8810 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);
8813 case Q3DEFORM_NORMAL:
8814 // deform the normals to make reflections wavey
8815 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8816 rsurface.batchnormal3f_vertexbuffer = NULL;
8817 rsurface.batchnormal3f_bufferoffset = 0;
8818 for (j = 0;j < batchnumvertices;j++)
8821 float *normal = rsurface.batchnormal3f + 3*j;
8822 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8823 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8824 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]);
8825 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]);
8826 VectorNormalize(normal);
8828 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8830 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8831 // rsurface.batchsvector3f_vertexbuffer = NULL;
8832 // rsurface.batchsvector3f_bufferoffset = 0;
8833 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8834 // rsurface.batchtvector3f_vertexbuffer = NULL;
8835 // rsurface.batchtvector3f_bufferoffset = 0;
8836 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);
8840 // deform vertex array to make wavey water and flags and such
8841 waveparms[0] = deform->waveparms[0];
8842 waveparms[1] = deform->waveparms[1];
8843 waveparms[2] = deform->waveparms[2];
8844 waveparms[3] = deform->waveparms[3];
8845 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8846 break; // if wavefunc is a nop, don't make a dynamic vertex array
8847 // this is how a divisor of vertex influence on deformation
8848 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8849 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8850 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8851 // rsurface.batchvertex3f_vertexbuffer = NULL;
8852 // rsurface.batchvertex3f_bufferoffset = 0;
8853 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8854 // rsurface.batchnormal3f_vertexbuffer = NULL;
8855 // rsurface.batchnormal3f_bufferoffset = 0;
8856 for (j = 0;j < batchnumvertices;j++)
8858 // if the wavefunc depends on time, evaluate it per-vertex
8861 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8862 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8864 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8866 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8867 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8868 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8870 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8871 // rsurface.batchsvector3f_vertexbuffer = NULL;
8872 // rsurface.batchsvector3f_bufferoffset = 0;
8873 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8874 // rsurface.batchtvector3f_vertexbuffer = NULL;
8875 // rsurface.batchtvector3f_bufferoffset = 0;
8876 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);
8879 case Q3DEFORM_BULGE:
8880 // deform vertex array to make the surface have moving bulges
8881 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8882 // rsurface.batchvertex3f_vertexbuffer = NULL;
8883 // rsurface.batchvertex3f_bufferoffset = 0;
8884 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8885 // rsurface.batchnormal3f_vertexbuffer = NULL;
8886 // rsurface.batchnormal3f_bufferoffset = 0;
8887 for (j = 0;j < batchnumvertices;j++)
8889 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
8890 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8892 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8893 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8894 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8896 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8897 // rsurface.batchsvector3f_vertexbuffer = NULL;
8898 // rsurface.batchsvector3f_bufferoffset = 0;
8899 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8900 // rsurface.batchtvector3f_vertexbuffer = NULL;
8901 // rsurface.batchtvector3f_bufferoffset = 0;
8902 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);
8906 // deform vertex array
8907 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8908 break; // if wavefunc is a nop, don't make a dynamic vertex array
8909 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8910 VectorScale(deform->parms, scale, waveparms);
8911 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8912 // rsurface.batchvertex3f_vertexbuffer = NULL;
8913 // rsurface.batchvertex3f_bufferoffset = 0;
8914 for (j = 0;j < batchnumvertices;j++)
8915 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8920 // generate texcoords based on the chosen texcoord source
8921 switch(rsurface.texture->tcgen.tcgen)
8924 case Q3TCGEN_TEXTURE:
8926 case Q3TCGEN_LIGHTMAP:
8927 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8928 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8929 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8930 if (rsurface.batchtexcoordlightmap2f)
8931 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
8933 case Q3TCGEN_VECTOR:
8934 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8935 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8936 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8937 for (j = 0;j < batchnumvertices;j++)
8939 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
8940 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
8943 case Q3TCGEN_ENVIRONMENT:
8944 // make environment reflections using a spheremap
8945 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8946 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8947 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8948 for (j = 0;j < batchnumvertices;j++)
8950 // identical to Q3A's method, but executed in worldspace so
8951 // carried models can be shiny too
8953 float viewer[3], d, reflected[3], worldreflected[3];
8955 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
8956 // VectorNormalize(viewer);
8958 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
8960 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
8961 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
8962 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
8963 // note: this is proportinal to viewer, so we can normalize later
8965 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
8966 VectorNormalize(worldreflected);
8968 // note: this sphere map only uses world x and z!
8969 // so positive and negative y will LOOK THE SAME.
8970 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
8971 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
8975 // the only tcmod that needs software vertex processing is turbulent, so
8976 // check for it here and apply the changes if needed
8977 // and we only support that as the first one
8978 // (handling a mixture of turbulent and other tcmods would be problematic
8979 // without punting it entirely to a software path)
8980 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8982 amplitude = rsurface.texture->tcmods[0].parms[1];
8983 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
8984 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8985 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8986 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8987 for (j = 0;j < batchnumvertices;j++)
8989 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);
8990 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
8994 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8996 // convert the modified arrays to vertex structs
8997 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8998 // rsurface.batchvertexmeshbuffer = NULL;
8999 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9000 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9001 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9002 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9003 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9004 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9005 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9007 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9009 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9010 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9013 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9014 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9015 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9016 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9017 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9018 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9019 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9020 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9021 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9025 void RSurf_DrawBatch(void)
9027 // sometimes a zero triangle surface (usually a degenerate patch) makes it
9028 // through the pipeline, killing it earlier in the pipeline would have
9029 // per-surface overhead rather than per-batch overhead, so it's best to
9030 // reject it here, before it hits glDraw.
9031 if (rsurface.batchnumtriangles == 0)
9034 // batch debugging code
9035 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9041 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9042 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9045 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9047 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9049 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9050 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);
9057 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);
9060 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9062 // pick the closest matching water plane
9063 int planeindex, vertexindex, bestplaneindex = -1;
9067 r_waterstate_waterplane_t *p;
9068 qboolean prepared = false;
9070 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9072 if(p->camera_entity != rsurface.texture->camera_entity)
9077 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9079 if(rsurface.batchnumvertices == 0)
9082 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9084 Matrix4x4_Transform(&rsurface.matrix, v, vert);
9085 d += fabs(PlaneDiff(vert, &p->plane));
9087 if (bestd > d || bestplaneindex < 0)
9090 bestplaneindex = planeindex;
9093 return bestplaneindex;
9094 // NOTE: this MAY return a totally unrelated water plane; we can ignore
9095 // this situation though, as it might be better to render single larger
9096 // batches with useless stuff (backface culled for example) than to
9097 // render multiple smaller batches
9100 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9103 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9104 rsurface.passcolor4f_vertexbuffer = 0;
9105 rsurface.passcolor4f_bufferoffset = 0;
9106 for (i = 0;i < rsurface.batchnumvertices;i++)
9107 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9110 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9117 if (rsurface.passcolor4f)
9119 // generate color arrays
9120 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9121 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9122 rsurface.passcolor4f_vertexbuffer = 0;
9123 rsurface.passcolor4f_bufferoffset = 0;
9124 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)
9126 f = RSurf_FogVertex(v);
9135 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9136 rsurface.passcolor4f_vertexbuffer = 0;
9137 rsurface.passcolor4f_bufferoffset = 0;
9138 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9140 f = RSurf_FogVertex(v);
9149 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9156 if (!rsurface.passcolor4f)
9158 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9159 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9160 rsurface.passcolor4f_vertexbuffer = 0;
9161 rsurface.passcolor4f_bufferoffset = 0;
9162 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)
9164 f = RSurf_FogVertex(v);
9165 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9166 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9167 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9172 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9177 if (!rsurface.passcolor4f)
9179 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9180 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9181 rsurface.passcolor4f_vertexbuffer = 0;
9182 rsurface.passcolor4f_bufferoffset = 0;
9183 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9192 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9197 if (!rsurface.passcolor4f)
9199 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9200 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9201 rsurface.passcolor4f_vertexbuffer = 0;
9202 rsurface.passcolor4f_bufferoffset = 0;
9203 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9205 c2[0] = c[0] + r_refdef.scene.ambient;
9206 c2[1] = c[1] + r_refdef.scene.ambient;
9207 c2[2] = c[2] + r_refdef.scene.ambient;
9212 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9215 rsurface.passcolor4f = NULL;
9216 rsurface.passcolor4f_vertexbuffer = 0;
9217 rsurface.passcolor4f_bufferoffset = 0;
9218 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9219 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9220 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9221 GL_Color(r, g, b, a);
9222 R_Mesh_TexBind(0, rsurface.lightmaptexture);
9226 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9228 // TODO: optimize applyfog && applycolor case
9229 // just apply fog if necessary, and tint the fog color array if necessary
9230 rsurface.passcolor4f = NULL;
9231 rsurface.passcolor4f_vertexbuffer = 0;
9232 rsurface.passcolor4f_bufferoffset = 0;
9233 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9234 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9235 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9236 GL_Color(r, g, b, a);
9240 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9243 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9244 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9245 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9246 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9247 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9248 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9249 GL_Color(r, g, b, a);
9253 static void RSurf_DrawBatch_GL11_ClampColor(void)
9258 if (!rsurface.passcolor4f)
9260 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9262 c2[0] = bound(0.0f, c1[0], 1.0f);
9263 c2[1] = bound(0.0f, c1[1], 1.0f);
9264 c2[2] = bound(0.0f, c1[2], 1.0f);
9265 c2[3] = bound(0.0f, c1[3], 1.0f);
9269 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9279 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9280 rsurface.passcolor4f_vertexbuffer = 0;
9281 rsurface.passcolor4f_bufferoffset = 0;
9282 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)
9284 f = -DotProduct(r_refdef.view.forward, n);
9286 f = f * 0.85 + 0.15; // work around so stuff won't get black
9287 f *= r_refdef.lightmapintensity;
9288 Vector4Set(c, f, f, f, 1);
9292 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9294 RSurf_DrawBatch_GL11_ApplyFakeLight();
9295 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9296 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9297 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9298 GL_Color(r, g, b, a);
9302 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9310 vec3_t ambientcolor;
9311 vec3_t diffusecolor;
9315 VectorCopy(rsurface.modellight_lightdir, lightdir);
9316 f = 0.5f * r_refdef.lightmapintensity;
9317 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9318 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9319 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9320 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9321 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9322 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9324 if (VectorLength2(diffusecolor) > 0)
9326 // q3-style directional shading
9327 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9328 rsurface.passcolor4f_vertexbuffer = 0;
9329 rsurface.passcolor4f_bufferoffset = 0;
9330 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)
9332 if ((f = DotProduct(n, lightdir)) > 0)
9333 VectorMA(ambientcolor, f, diffusecolor, c);
9335 VectorCopy(ambientcolor, c);
9342 *applycolor = false;
9346 *r = ambientcolor[0];
9347 *g = ambientcolor[1];
9348 *b = ambientcolor[2];
9349 rsurface.passcolor4f = NULL;
9350 rsurface.passcolor4f_vertexbuffer = 0;
9351 rsurface.passcolor4f_bufferoffset = 0;
9355 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9357 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9358 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9359 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9360 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9361 GL_Color(r, g, b, a);
9365 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9373 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9374 rsurface.passcolor4f_vertexbuffer = 0;
9375 rsurface.passcolor4f_bufferoffset = 0;
9377 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9379 f = 1 - RSurf_FogVertex(v);
9387 void RSurf_SetupDepthAndCulling(void)
9389 // submodels are biased to avoid z-fighting with world surfaces that they
9390 // may be exactly overlapping (avoids z-fighting artifacts on certain
9391 // doors and things in Quake maps)
9392 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9393 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9394 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9395 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9398 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9400 // transparent sky would be ridiculous
9401 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9403 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9404 skyrenderlater = true;
9405 RSurf_SetupDepthAndCulling();
9407 // LordHavoc: HalfLife maps have freaky skypolys so don't use
9408 // skymasking on them, and Quake3 never did sky masking (unlike
9409 // software Quake and software Quake2), so disable the sky masking
9410 // in Quake3 maps as it causes problems with q3map2 sky tricks,
9411 // and skymasking also looks very bad when noclipping outside the
9412 // level, so don't use it then either.
9413 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9415 R_Mesh_ResetTextureState();
9416 if (skyrendermasked)
9418 R_SetupShader_DepthOrShadow();
9419 // depth-only (masking)
9420 GL_ColorMask(0,0,0,0);
9421 // just to make sure that braindead drivers don't draw
9422 // anything despite that colormask...
9423 GL_BlendFunc(GL_ZERO, GL_ONE);
9424 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9425 if (rsurface.batchvertex3fbuffer)
9426 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9428 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9432 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9434 GL_BlendFunc(GL_ONE, GL_ZERO);
9435 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9436 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9437 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9440 if (skyrendermasked)
9441 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9443 R_Mesh_ResetTextureState();
9444 GL_Color(1, 1, 1, 1);
9447 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9448 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9449 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9451 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9455 // render screenspace normalmap to texture
9457 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9461 // bind lightmap texture
9463 // water/refraction/reflection/camera surfaces have to be handled specially
9464 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9466 int start, end, startplaneindex;
9467 for (start = 0;start < texturenumsurfaces;start = end)
9469 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9470 if(startplaneindex < 0)
9472 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9473 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9477 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9479 // now that we have a batch using the same planeindex, render it
9480 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9482 // render water or distortion background
9484 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));
9486 // blend surface on top
9487 GL_DepthMask(false);
9488 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9491 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9493 // render surface with reflection texture as input
9494 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9495 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));
9502 // render surface batch normally
9503 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9504 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
9505 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9508 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9509 GL_AlphaTest(false);
9512 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9514 // OpenGL 1.3 path - anything not completely ancient
9515 qboolean applycolor;
9518 const texturelayer_t *layer;
9519 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);
9520 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9522 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9525 int layertexrgbscale;
9526 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9528 if (layerindex == 0)
9532 GL_AlphaTest(false);
9533 GL_DepthFunc(GL_EQUAL);
9536 GL_DepthMask(layer->depthmask && writedepth);
9537 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9538 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9540 layertexrgbscale = 4;
9541 VectorScale(layer->color, 0.25f, layercolor);
9543 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9545 layertexrgbscale = 2;
9546 VectorScale(layer->color, 0.5f, layercolor);
9550 layertexrgbscale = 1;
9551 VectorScale(layer->color, 1.0f, layercolor);
9553 layercolor[3] = layer->color[3];
9554 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9555 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9556 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9557 switch (layer->type)
9559 case TEXTURELAYERTYPE_LITTEXTURE:
9560 // single-pass lightmapped texture with 2x rgbscale
9561 R_Mesh_TexBind(0, r_texture_white);
9562 R_Mesh_TexMatrix(0, NULL);
9563 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9564 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9565 R_Mesh_TexBind(1, layer->texture);
9566 R_Mesh_TexMatrix(1, &layer->texmatrix);
9567 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9568 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9569 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9570 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9571 else if (FAKELIGHT_ENABLED)
9572 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9573 else if (rsurface.uselightmaptexture)
9574 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9576 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9578 case TEXTURELAYERTYPE_TEXTURE:
9579 // singletexture unlit texture with transparency support
9580 R_Mesh_TexBind(0, layer->texture);
9581 R_Mesh_TexMatrix(0, &layer->texmatrix);
9582 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9583 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9584 R_Mesh_TexBind(1, 0);
9585 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9586 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9588 case TEXTURELAYERTYPE_FOG:
9589 // singletexture fogging
9592 R_Mesh_TexBind(0, layer->texture);
9593 R_Mesh_TexMatrix(0, &layer->texmatrix);
9594 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9595 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9599 R_Mesh_TexBind(0, 0);
9600 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9602 R_Mesh_TexBind(1, 0);
9603 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9604 // generate a color array for the fog pass
9605 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9606 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9610 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9613 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9615 GL_DepthFunc(GL_LEQUAL);
9616 GL_AlphaTest(false);
9620 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9622 // OpenGL 1.1 - crusty old voodoo path
9625 const texturelayer_t *layer;
9626 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);
9627 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9629 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9631 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9633 if (layerindex == 0)
9637 GL_AlphaTest(false);
9638 GL_DepthFunc(GL_EQUAL);
9641 GL_DepthMask(layer->depthmask && writedepth);
9642 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9643 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9644 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9645 switch (layer->type)
9647 case TEXTURELAYERTYPE_LITTEXTURE:
9648 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9650 // two-pass lit texture with 2x rgbscale
9651 // first the lightmap pass
9652 R_Mesh_TexBind(0, r_texture_white);
9653 R_Mesh_TexMatrix(0, NULL);
9654 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9655 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9656 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9657 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9658 else if (FAKELIGHT_ENABLED)
9659 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9660 else if (rsurface.uselightmaptexture)
9661 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9663 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9664 // then apply the texture to it
9665 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9666 R_Mesh_TexBind(0, layer->texture);
9667 R_Mesh_TexMatrix(0, &layer->texmatrix);
9668 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9669 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9670 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);
9674 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9675 R_Mesh_TexBind(0, layer->texture);
9676 R_Mesh_TexMatrix(0, &layer->texmatrix);
9677 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9678 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9679 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9680 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);
9682 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);
9685 case TEXTURELAYERTYPE_TEXTURE:
9686 // singletexture unlit texture with transparency support
9687 R_Mesh_TexBind(0, layer->texture);
9688 R_Mesh_TexMatrix(0, &layer->texmatrix);
9689 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9690 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9691 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);
9693 case TEXTURELAYERTYPE_FOG:
9694 // singletexture fogging
9697 R_Mesh_TexBind(0, layer->texture);
9698 R_Mesh_TexMatrix(0, &layer->texmatrix);
9699 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9700 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9704 R_Mesh_TexBind(0, 0);
9705 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9707 // generate a color array for the fog pass
9708 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9709 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9713 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9716 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9718 GL_DepthFunc(GL_LEQUAL);
9719 GL_AlphaTest(false);
9723 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9727 r_vertexgeneric_t *batchvertex;
9730 // R_Mesh_ResetTextureState();
9731 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9733 if(rsurface.texture && rsurface.texture->currentskinframe)
9735 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9736 c[3] *= rsurface.texture->currentalpha;
9746 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9748 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9749 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9750 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9753 // brighten it up (as texture value 127 means "unlit")
9754 c[0] *= 2 * r_refdef.view.colorscale;
9755 c[1] *= 2 * r_refdef.view.colorscale;
9756 c[2] *= 2 * r_refdef.view.colorscale;
9758 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9759 c[3] *= r_wateralpha.value;
9761 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9763 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9764 GL_DepthMask(false);
9766 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9768 GL_BlendFunc(GL_ONE, GL_ONE);
9769 GL_DepthMask(false);
9771 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9773 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9774 GL_DepthMask(false);
9776 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9778 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9779 GL_DepthMask(false);
9783 GL_BlendFunc(GL_ONE, GL_ZERO);
9784 GL_DepthMask(writedepth);
9787 if (r_showsurfaces.integer == 3)
9789 rsurface.passcolor4f = NULL;
9791 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9793 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9795 rsurface.passcolor4f = NULL;
9796 rsurface.passcolor4f_vertexbuffer = 0;
9797 rsurface.passcolor4f_bufferoffset = 0;
9799 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9801 qboolean applycolor = true;
9804 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9806 r_refdef.lightmapintensity = 1;
9807 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9808 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9810 else if (FAKELIGHT_ENABLED)
9812 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9814 r_refdef.lightmapintensity = r_fakelight_intensity.value;
9815 RSurf_DrawBatch_GL11_ApplyFakeLight();
9816 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9820 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9822 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9823 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9824 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9827 if(!rsurface.passcolor4f)
9828 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9830 RSurf_DrawBatch_GL11_ApplyAmbient();
9831 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9832 if(r_refdef.fogenabled)
9833 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9834 RSurf_DrawBatch_GL11_ClampColor();
9836 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9837 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9840 else if (!r_refdef.view.showdebug)
9842 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9843 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9844 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9846 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9847 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9849 R_Mesh_PrepareVertices_Generic_Unlock();
9852 else if (r_showsurfaces.integer == 4)
9854 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9855 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9856 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9858 unsigned char c = (vi << 3) * (1.0f / 256.0f);
9859 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9860 Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9862 R_Mesh_PrepareVertices_Generic_Unlock();
9865 else if (r_showsurfaces.integer == 2)
9868 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9869 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9870 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9872 unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9873 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9874 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9875 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9876 Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9877 Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9878 Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9880 R_Mesh_PrepareVertices_Generic_Unlock();
9881 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9885 int texturesurfaceindex;
9887 const msurface_t *surface;
9888 float surfacecolor4f[4];
9889 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9890 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9892 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9894 surface = texturesurfacelist[texturesurfaceindex];
9895 k = (int)(((size_t)surface) / sizeof(msurface_t));
9896 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9897 for (j = 0;j < surface->num_vertices;j++)
9899 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9900 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
9904 R_Mesh_PrepareVertices_Generic_Unlock();
9909 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9912 RSurf_SetupDepthAndCulling();
9913 if (r_showsurfaces.integer)
9915 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9918 switch (vid.renderpath)
9920 case RENDERPATH_GL20:
9921 case RENDERPATH_D3D9:
9922 case RENDERPATH_D3D10:
9923 case RENDERPATH_D3D11:
9924 case RENDERPATH_SOFT:
9925 case RENDERPATH_GLES2:
9926 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9928 case RENDERPATH_GL13:
9929 case RENDERPATH_GLES1:
9930 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9932 case RENDERPATH_GL11:
9933 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9939 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9942 RSurf_SetupDepthAndCulling();
9943 if (r_showsurfaces.integer)
9945 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9948 switch (vid.renderpath)
9950 case RENDERPATH_GL20:
9951 case RENDERPATH_D3D9:
9952 case RENDERPATH_D3D10:
9953 case RENDERPATH_D3D11:
9954 case RENDERPATH_SOFT:
9955 case RENDERPATH_GLES2:
9956 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9958 case RENDERPATH_GL13:
9959 case RENDERPATH_GLES1:
9960 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9962 case RENDERPATH_GL11:
9963 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9969 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9972 int texturenumsurfaces, endsurface;
9974 const msurface_t *surface;
9975 const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
9977 // if the model is static it doesn't matter what value we give for
9978 // wantnormals and wanttangents, so this logic uses only rules applicable
9979 // to a model, knowing that they are meaningless otherwise
9980 if (ent == r_refdef.scene.worldentity)
9981 RSurf_ActiveWorldEntity();
9982 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9983 RSurf_ActiveModelEntity(ent, false, false, false);
9986 switch (vid.renderpath)
9988 case RENDERPATH_GL20:
9989 case RENDERPATH_D3D9:
9990 case RENDERPATH_D3D10:
9991 case RENDERPATH_D3D11:
9992 case RENDERPATH_SOFT:
9993 case RENDERPATH_GLES2:
9994 RSurf_ActiveModelEntity(ent, true, true, false);
9996 case RENDERPATH_GL11:
9997 case RENDERPATH_GL13:
9998 case RENDERPATH_GLES1:
9999 RSurf_ActiveModelEntity(ent, true, false, false);
10004 if (r_transparentdepthmasking.integer)
10006 qboolean setup = false;
10007 for (i = 0;i < numsurfaces;i = j)
10010 surface = rsurface.modelsurfaces + surfacelist[i];
10011 texture = surface->texture;
10012 rsurface.texture = R_GetCurrentTexture(texture);
10013 rsurface.lightmaptexture = NULL;
10014 rsurface.deluxemaptexture = NULL;
10015 rsurface.uselightmaptexture = false;
10016 // scan ahead until we find a different texture
10017 endsurface = min(i + 1024, numsurfaces);
10018 texturenumsurfaces = 0;
10019 texturesurfacelist[texturenumsurfaces++] = surface;
10020 for (;j < endsurface;j++)
10022 surface = rsurface.modelsurfaces + surfacelist[j];
10023 if (texture != surface->texture)
10025 texturesurfacelist[texturenumsurfaces++] = surface;
10027 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10029 // render the range of surfaces as depth
10033 GL_ColorMask(0,0,0,0);
10035 GL_DepthTest(true);
10036 GL_BlendFunc(GL_ONE, GL_ZERO);
10037 GL_DepthMask(true);
10038 // R_Mesh_ResetTextureState();
10039 R_SetupShader_DepthOrShadow();
10041 RSurf_SetupDepthAndCulling();
10042 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10043 if (rsurface.batchvertex3fbuffer)
10044 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10046 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10050 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10053 for (i = 0;i < numsurfaces;i = j)
10056 surface = rsurface.modelsurfaces + surfacelist[i];
10057 texture = surface->texture;
10058 rsurface.texture = R_GetCurrentTexture(texture);
10059 // scan ahead until we find a different texture
10060 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10061 texturenumsurfaces = 0;
10062 texturesurfacelist[texturenumsurfaces++] = surface;
10063 if(FAKELIGHT_ENABLED)
10065 rsurface.lightmaptexture = NULL;
10066 rsurface.deluxemaptexture = NULL;
10067 rsurface.uselightmaptexture = false;
10068 for (;j < endsurface;j++)
10070 surface = rsurface.modelsurfaces + surfacelist[j];
10071 if (texture != surface->texture)
10073 texturesurfacelist[texturenumsurfaces++] = surface;
10078 rsurface.lightmaptexture = surface->lightmaptexture;
10079 rsurface.deluxemaptexture = surface->deluxemaptexture;
10080 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10081 for (;j < endsurface;j++)
10083 surface = rsurface.modelsurfaces + surfacelist[j];
10084 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10086 texturesurfacelist[texturenumsurfaces++] = surface;
10089 // render the range of surfaces
10090 if (ent == r_refdef.scene.worldentity)
10091 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10093 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10095 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10098 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10100 // transparent surfaces get pushed off into the transparent queue
10101 int surfacelistindex;
10102 const msurface_t *surface;
10103 vec3_t tempcenter, center;
10104 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10106 surface = texturesurfacelist[surfacelistindex];
10107 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10108 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10109 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10110 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10111 if (queueentity->transparent_offset) // transparent offset
10113 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10114 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10115 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10117 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10121 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10123 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10125 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10127 RSurf_SetupDepthAndCulling();
10128 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10129 if (rsurface.batchvertex3fbuffer)
10130 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10132 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10136 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10138 const entity_render_t *queueentity = r_refdef.scene.worldentity;
10141 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10144 if (!rsurface.texture->currentnumlayers)
10146 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10147 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10149 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10151 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10152 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10153 else if (!rsurface.texture->currentnumlayers)
10155 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10157 // in the deferred case, transparent surfaces were queued during prepass
10158 if (!r_shadow_usingdeferredprepass)
10159 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10163 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10164 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10169 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10172 texture_t *texture;
10173 R_FrameData_SetMark();
10174 // break the surface list down into batches by texture and use of lightmapping
10175 for (i = 0;i < numsurfaces;i = j)
10178 // texture is the base texture pointer, rsurface.texture is the
10179 // current frame/skin the texture is directing us to use (for example
10180 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10181 // use skin 1 instead)
10182 texture = surfacelist[i]->texture;
10183 rsurface.texture = R_GetCurrentTexture(texture);
10184 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10186 // if this texture is not the kind we want, skip ahead to the next one
10187 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10191 if(FAKELIGHT_ENABLED || depthonly || prepass)
10193 rsurface.lightmaptexture = NULL;
10194 rsurface.deluxemaptexture = NULL;
10195 rsurface.uselightmaptexture = false;
10196 // simply scan ahead until we find a different texture or lightmap state
10197 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10202 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10203 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10204 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10205 // simply scan ahead until we find a different texture or lightmap state
10206 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10209 // render the range of surfaces
10210 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10212 R_FrameData_ReturnToMark();
10215 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10219 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10222 if (!rsurface.texture->currentnumlayers)
10224 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10225 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10227 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10229 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10230 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10231 else if (!rsurface.texture->currentnumlayers)
10233 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10235 // in the deferred case, transparent surfaces were queued during prepass
10236 if (!r_shadow_usingdeferredprepass)
10237 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10241 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10242 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10247 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10250 texture_t *texture;
10251 R_FrameData_SetMark();
10252 // break the surface list down into batches by texture and use of lightmapping
10253 for (i = 0;i < numsurfaces;i = j)
10256 // texture is the base texture pointer, rsurface.texture is the
10257 // current frame/skin the texture is directing us to use (for example
10258 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10259 // use skin 1 instead)
10260 texture = surfacelist[i]->texture;
10261 rsurface.texture = R_GetCurrentTexture(texture);
10262 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10264 // if this texture is not the kind we want, skip ahead to the next one
10265 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10269 if(FAKELIGHT_ENABLED || depthonly || prepass)
10271 rsurface.lightmaptexture = NULL;
10272 rsurface.deluxemaptexture = NULL;
10273 rsurface.uselightmaptexture = false;
10274 // simply scan ahead until we find a different texture or lightmap state
10275 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10280 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10281 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10282 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10283 // simply scan ahead until we find a different texture or lightmap state
10284 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10287 // render the range of surfaces
10288 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10290 R_FrameData_ReturnToMark();
10293 float locboxvertex3f[6*4*3] =
10295 1,0,1, 1,0,0, 1,1,0, 1,1,1,
10296 0,1,1, 0,1,0, 0,0,0, 0,0,1,
10297 1,1,1, 1,1,0, 0,1,0, 0,1,1,
10298 0,0,1, 0,0,0, 1,0,0, 1,0,1,
10299 0,0,1, 1,0,1, 1,1,1, 0,1,1,
10300 1,0,0, 0,0,0, 0,1,0, 1,1,0
10303 unsigned short locboxelements[6*2*3] =
10308 12,13,14, 12,14,15,
10309 16,17,18, 16,18,19,
10313 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10316 cl_locnode_t *loc = (cl_locnode_t *)ent;
10318 float vertex3f[6*4*3];
10320 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10321 GL_DepthMask(false);
10322 GL_DepthRange(0, 1);
10323 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10324 GL_DepthTest(true);
10325 GL_CullFace(GL_NONE);
10326 R_EntityMatrix(&identitymatrix);
10328 // R_Mesh_ResetTextureState();
10330 i = surfacelist[0];
10331 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10332 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10333 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10334 surfacelist[0] < 0 ? 0.5f : 0.125f);
10336 if (VectorCompare(loc->mins, loc->maxs))
10338 VectorSet(size, 2, 2, 2);
10339 VectorMA(loc->mins, -0.5f, size, mins);
10343 VectorCopy(loc->mins, mins);
10344 VectorSubtract(loc->maxs, loc->mins, size);
10347 for (i = 0;i < 6*4*3;)
10348 for (j = 0;j < 3;j++, i++)
10349 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10351 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10352 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10353 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10356 void R_DrawLocs(void)
10359 cl_locnode_t *loc, *nearestloc;
10361 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10362 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10364 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10365 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10369 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10371 if (decalsystem->decals)
10372 Mem_Free(decalsystem->decals);
10373 memset(decalsystem, 0, sizeof(*decalsystem));
10376 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)
10379 tridecal_t *decals;
10382 // expand or initialize the system
10383 if (decalsystem->maxdecals <= decalsystem->numdecals)
10385 decalsystem_t old = *decalsystem;
10386 qboolean useshortelements;
10387 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10388 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10389 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)));
10390 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10391 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10392 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10393 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10394 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10395 if (decalsystem->numdecals)
10396 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10398 Mem_Free(old.decals);
10399 for (i = 0;i < decalsystem->maxdecals*3;i++)
10400 decalsystem->element3i[i] = i;
10401 if (useshortelements)
10402 for (i = 0;i < decalsystem->maxdecals*3;i++)
10403 decalsystem->element3s[i] = i;
10406 // grab a decal and search for another free slot for the next one
10407 decals = decalsystem->decals;
10408 decal = decalsystem->decals + (i = decalsystem->freedecal++);
10409 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10411 decalsystem->freedecal = i;
10412 if (decalsystem->numdecals <= i)
10413 decalsystem->numdecals = i + 1;
10415 // initialize the decal
10417 decal->triangleindex = triangleindex;
10418 decal->surfaceindex = surfaceindex;
10419 decal->decalsequence = decalsequence;
10420 decal->color4f[0][0] = c0[0];
10421 decal->color4f[0][1] = c0[1];
10422 decal->color4f[0][2] = c0[2];
10423 decal->color4f[0][3] = 1;
10424 decal->color4f[1][0] = c1[0];
10425 decal->color4f[1][1] = c1[1];
10426 decal->color4f[1][2] = c1[2];
10427 decal->color4f[1][3] = 1;
10428 decal->color4f[2][0] = c2[0];
10429 decal->color4f[2][1] = c2[1];
10430 decal->color4f[2][2] = c2[2];
10431 decal->color4f[2][3] = 1;
10432 decal->vertex3f[0][0] = v0[0];
10433 decal->vertex3f[0][1] = v0[1];
10434 decal->vertex3f[0][2] = v0[2];
10435 decal->vertex3f[1][0] = v1[0];
10436 decal->vertex3f[1][1] = v1[1];
10437 decal->vertex3f[1][2] = v1[2];
10438 decal->vertex3f[2][0] = v2[0];
10439 decal->vertex3f[2][1] = v2[1];
10440 decal->vertex3f[2][2] = v2[2];
10441 decal->texcoord2f[0][0] = t0[0];
10442 decal->texcoord2f[0][1] = t0[1];
10443 decal->texcoord2f[1][0] = t1[0];
10444 decal->texcoord2f[1][1] = t1[1];
10445 decal->texcoord2f[2][0] = t2[0];
10446 decal->texcoord2f[2][1] = t2[1];
10447 TriangleNormal(v0, v1, v2, decal->plane);
10448 VectorNormalize(decal->plane);
10449 decal->plane[3] = DotProduct(v0, decal->plane);
10452 extern cvar_t cl_decals_bias;
10453 extern cvar_t cl_decals_models;
10454 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10455 // baseparms, parms, temps
10456 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)
10461 const float *vertex3f;
10462 const float *normal3f;
10464 float points[2][9][3];
10471 e = rsurface.modelelement3i + 3*triangleindex;
10473 vertex3f = rsurface.modelvertex3f;
10474 normal3f = rsurface.modelnormal3f;
10478 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10480 index = 3*e[cornerindex];
10481 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10486 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10488 index = 3*e[cornerindex];
10489 VectorCopy(vertex3f + index, v[cornerindex]);
10494 //TriangleNormal(v[0], v[1], v[2], normal);
10495 //if (DotProduct(normal, localnormal) < 0.0f)
10497 // clip by each of the box planes formed from the projection matrix
10498 // if anything survives, we emit the decal
10499 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]);
10502 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]);
10505 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]);
10508 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]);
10511 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]);
10514 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]);
10517 // some part of the triangle survived, so we have to accept it...
10520 // dynamic always uses the original triangle
10522 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10524 index = 3*e[cornerindex];
10525 VectorCopy(vertex3f + index, v[cornerindex]);
10528 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10530 // convert vertex positions to texcoords
10531 Matrix4x4_Transform(projection, v[cornerindex], temp);
10532 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10533 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10534 // calculate distance fade from the projection origin
10535 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10536 f = bound(0.0f, f, 1.0f);
10537 c[cornerindex][0] = r * f;
10538 c[cornerindex][1] = g * f;
10539 c[cornerindex][2] = b * f;
10540 c[cornerindex][3] = 1.0f;
10541 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10544 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);
10546 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10547 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);
10549 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)
10551 matrix4x4_t projection;
10552 decalsystem_t *decalsystem;
10555 const msurface_t *surface;
10556 const msurface_t *surfaces;
10557 const int *surfacelist;
10558 const texture_t *texture;
10560 int numsurfacelist;
10561 int surfacelistindex;
10564 float localorigin[3];
10565 float localnormal[3];
10566 float localmins[3];
10567 float localmaxs[3];
10570 float planes[6][4];
10573 int bih_triangles_count;
10574 int bih_triangles[256];
10575 int bih_surfaces[256];
10577 decalsystem = &ent->decalsystem;
10578 model = ent->model;
10579 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10581 R_DecalSystem_Reset(&ent->decalsystem);
10585 if (!model->brush.data_leafs && !cl_decals_models.integer)
10587 if (decalsystem->model)
10588 R_DecalSystem_Reset(decalsystem);
10592 if (decalsystem->model != model)
10593 R_DecalSystem_Reset(decalsystem);
10594 decalsystem->model = model;
10596 RSurf_ActiveModelEntity(ent, true, false, false);
10598 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10599 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10600 VectorNormalize(localnormal);
10601 localsize = worldsize*rsurface.inversematrixscale;
10602 localmins[0] = localorigin[0] - localsize;
10603 localmins[1] = localorigin[1] - localsize;
10604 localmins[2] = localorigin[2] - localsize;
10605 localmaxs[0] = localorigin[0] + localsize;
10606 localmaxs[1] = localorigin[1] + localsize;
10607 localmaxs[2] = localorigin[2] + localsize;
10609 //VectorCopy(localnormal, planes[4]);
10610 //VectorVectors(planes[4], planes[2], planes[0]);
10611 AnglesFromVectors(angles, localnormal, NULL, false);
10612 AngleVectors(angles, planes[0], planes[2], planes[4]);
10613 VectorNegate(planes[0], planes[1]);
10614 VectorNegate(planes[2], planes[3]);
10615 VectorNegate(planes[4], planes[5]);
10616 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10617 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10618 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10619 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10620 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10621 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10626 matrix4x4_t forwardprojection;
10627 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10628 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10633 float projectionvector[4][3];
10634 VectorScale(planes[0], ilocalsize, projectionvector[0]);
10635 VectorScale(planes[2], ilocalsize, projectionvector[1]);
10636 VectorScale(planes[4], ilocalsize, projectionvector[2]);
10637 projectionvector[0][0] = planes[0][0] * ilocalsize;
10638 projectionvector[0][1] = planes[1][0] * ilocalsize;
10639 projectionvector[0][2] = planes[2][0] * ilocalsize;
10640 projectionvector[1][0] = planes[0][1] * ilocalsize;
10641 projectionvector[1][1] = planes[1][1] * ilocalsize;
10642 projectionvector[1][2] = planes[2][1] * ilocalsize;
10643 projectionvector[2][0] = planes[0][2] * ilocalsize;
10644 projectionvector[2][1] = planes[1][2] * ilocalsize;
10645 projectionvector[2][2] = planes[2][2] * ilocalsize;
10646 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10647 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10648 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10649 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10653 dynamic = model->surfmesh.isanimated;
10654 numsurfacelist = model->nummodelsurfaces;
10655 surfacelist = model->sortedmodelsurfaces;
10656 surfaces = model->data_surfaces;
10659 bih_triangles_count = -1;
10662 if(model->render_bih.numleafs)
10663 bih = &model->render_bih;
10664 else if(model->collision_bih.numleafs)
10665 bih = &model->collision_bih;
10668 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10669 if(bih_triangles_count == 0)
10671 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10673 if(bih_triangles_count > 0)
10675 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10677 surfaceindex = bih_surfaces[triangleindex];
10678 surface = surfaces + surfaceindex;
10679 texture = surface->texture;
10680 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10682 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10684 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10689 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10691 surfaceindex = surfacelist[surfacelistindex];
10692 surface = surfaces + surfaceindex;
10693 // check cull box first because it rejects more than any other check
10694 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10696 // skip transparent surfaces
10697 texture = surface->texture;
10698 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10700 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10702 numtriangles = surface->num_triangles;
10703 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10704 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10709 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10710 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)
10712 int renderentityindex;
10713 float worldmins[3];
10714 float worldmaxs[3];
10715 entity_render_t *ent;
10717 if (!cl_decals_newsystem.integer)
10720 worldmins[0] = worldorigin[0] - worldsize;
10721 worldmins[1] = worldorigin[1] - worldsize;
10722 worldmins[2] = worldorigin[2] - worldsize;
10723 worldmaxs[0] = worldorigin[0] + worldsize;
10724 worldmaxs[1] = worldorigin[1] + worldsize;
10725 worldmaxs[2] = worldorigin[2] + worldsize;
10727 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10729 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10731 ent = r_refdef.scene.entities[renderentityindex];
10732 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10735 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10739 typedef struct r_decalsystem_splatqueue_s
10741 vec3_t worldorigin;
10742 vec3_t worldnormal;
10748 r_decalsystem_splatqueue_t;
10750 int r_decalsystem_numqueued = 0;
10751 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10753 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)
10755 r_decalsystem_splatqueue_t *queue;
10757 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10760 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10761 VectorCopy(worldorigin, queue->worldorigin);
10762 VectorCopy(worldnormal, queue->worldnormal);
10763 Vector4Set(queue->color, r, g, b, a);
10764 Vector4Set(queue->tcrange, s1, t1, s2, t2);
10765 queue->worldsize = worldsize;
10766 queue->decalsequence = cl.decalsequence++;
10769 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10772 r_decalsystem_splatqueue_t *queue;
10774 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10775 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);
10776 r_decalsystem_numqueued = 0;
10779 extern cvar_t cl_decals_max;
10780 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10783 decalsystem_t *decalsystem = &ent->decalsystem;
10790 if (!decalsystem->numdecals)
10793 if (r_showsurfaces.integer)
10796 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10798 R_DecalSystem_Reset(decalsystem);
10802 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10803 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10805 if (decalsystem->lastupdatetime)
10806 frametime = (cl.time - decalsystem->lastupdatetime);
10809 decalsystem->lastupdatetime = cl.time;
10810 decal = decalsystem->decals;
10811 numdecals = decalsystem->numdecals;
10813 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10815 if (decal->color4f[0][3])
10817 decal->lived += frametime;
10818 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10820 memset(decal, 0, sizeof(*decal));
10821 if (decalsystem->freedecal > i)
10822 decalsystem->freedecal = i;
10826 decal = decalsystem->decals;
10827 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10830 // collapse the array by shuffling the tail decals into the gaps
10833 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10834 decalsystem->freedecal++;
10835 if (decalsystem->freedecal == numdecals)
10837 decal[decalsystem->freedecal] = decal[--numdecals];
10840 decalsystem->numdecals = numdecals;
10842 if (numdecals <= 0)
10844 // if there are no decals left, reset decalsystem
10845 R_DecalSystem_Reset(decalsystem);
10849 extern skinframe_t *decalskinframe;
10850 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10853 decalsystem_t *decalsystem = &ent->decalsystem;
10862 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10865 numdecals = decalsystem->numdecals;
10869 if (r_showsurfaces.integer)
10872 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10874 R_DecalSystem_Reset(decalsystem);
10878 // if the model is static it doesn't matter what value we give for
10879 // wantnormals and wanttangents, so this logic uses only rules applicable
10880 // to a model, knowing that they are meaningless otherwise
10881 if (ent == r_refdef.scene.worldentity)
10882 RSurf_ActiveWorldEntity();
10884 RSurf_ActiveModelEntity(ent, false, false, false);
10886 decalsystem->lastupdatetime = cl.time;
10887 decal = decalsystem->decals;
10889 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10891 // update vertex positions for animated models
10892 v3f = decalsystem->vertex3f;
10893 c4f = decalsystem->color4f;
10894 t2f = decalsystem->texcoord2f;
10895 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10897 if (!decal->color4f[0][3])
10900 if (surfacevisible && !surfacevisible[decal->surfaceindex])
10904 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
10907 // update color values for fading decals
10908 if (decal->lived >= cl_decals_time.value)
10909 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
10913 c4f[ 0] = decal->color4f[0][0] * alpha;
10914 c4f[ 1] = decal->color4f[0][1] * alpha;
10915 c4f[ 2] = decal->color4f[0][2] * alpha;
10917 c4f[ 4] = decal->color4f[1][0] * alpha;
10918 c4f[ 5] = decal->color4f[1][1] * alpha;
10919 c4f[ 6] = decal->color4f[1][2] * alpha;
10921 c4f[ 8] = decal->color4f[2][0] * alpha;
10922 c4f[ 9] = decal->color4f[2][1] * alpha;
10923 c4f[10] = decal->color4f[2][2] * alpha;
10926 t2f[0] = decal->texcoord2f[0][0];
10927 t2f[1] = decal->texcoord2f[0][1];
10928 t2f[2] = decal->texcoord2f[1][0];
10929 t2f[3] = decal->texcoord2f[1][1];
10930 t2f[4] = decal->texcoord2f[2][0];
10931 t2f[5] = decal->texcoord2f[2][1];
10933 // update vertex positions for animated models
10934 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
10936 e = rsurface.modelelement3i + 3*decal->triangleindex;
10937 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
10938 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
10939 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
10943 VectorCopy(decal->vertex3f[0], v3f);
10944 VectorCopy(decal->vertex3f[1], v3f + 3);
10945 VectorCopy(decal->vertex3f[2], v3f + 6);
10948 if (r_refdef.fogenabled)
10950 alpha = RSurf_FogVertex(v3f);
10951 VectorScale(c4f, alpha, c4f);
10952 alpha = RSurf_FogVertex(v3f + 3);
10953 VectorScale(c4f + 4, alpha, c4f + 4);
10954 alpha = RSurf_FogVertex(v3f + 6);
10955 VectorScale(c4f + 8, alpha, c4f + 8);
10966 r_refdef.stats.drawndecals += numtris;
10968 // now render the decals all at once
10969 // (this assumes they all use one particle font texture!)
10970 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);
10971 // R_Mesh_ResetTextureState();
10972 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
10973 GL_DepthMask(false);
10974 GL_DepthRange(0, 1);
10975 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
10976 GL_DepthTest(true);
10977 GL_CullFace(GL_NONE);
10978 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
10979 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
10980 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
10984 static void R_DrawModelDecals(void)
10988 // fade faster when there are too many decals
10989 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10990 for (i = 0;i < r_refdef.scene.numentities;i++)
10991 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10993 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
10994 for (i = 0;i < r_refdef.scene.numentities;i++)
10995 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10996 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
10998 R_DecalSystem_ApplySplatEntitiesQueue();
11000 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11001 for (i = 0;i < r_refdef.scene.numentities;i++)
11002 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11004 r_refdef.stats.totaldecals += numdecals;
11006 if (r_showsurfaces.integer)
11009 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11011 for (i = 0;i < r_refdef.scene.numentities;i++)
11013 if (!r_refdef.viewcache.entityvisible[i])
11015 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11016 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11020 extern cvar_t mod_collision_bih;
11021 void R_DrawDebugModel(void)
11023 entity_render_t *ent = rsurface.entity;
11024 int i, j, k, l, flagsmask;
11025 const msurface_t *surface;
11026 dp_model_t *model = ent->model;
11029 if (!sv.active && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11032 if (r_showoverdraw.value > 0)
11034 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11035 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11036 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11037 GL_DepthTest(false);
11038 GL_DepthMask(false);
11039 GL_DepthRange(0, 1);
11040 GL_BlendFunc(GL_ONE, GL_ONE);
11041 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11043 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11045 rsurface.texture = R_GetCurrentTexture(surface->texture);
11046 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11048 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11049 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11050 if (!rsurface.texture->currentlayers->depthmask)
11051 GL_Color(c, 0, 0, 1.0f);
11052 else if (ent == r_refdef.scene.worldentity)
11053 GL_Color(c, c, c, 1.0f);
11055 GL_Color(0, c, 0, 1.0f);
11056 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11060 rsurface.texture = NULL;
11063 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11065 // R_Mesh_ResetTextureState();
11066 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11067 GL_DepthRange(0, 1);
11068 GL_DepthTest(!r_showdisabledepthtest.integer);
11069 GL_DepthMask(false);
11070 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11072 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11076 qboolean cullbox = ent == r_refdef.scene.worldentity;
11077 const q3mbrush_t *brush;
11078 const bih_t *bih = &model->collision_bih;
11079 const bih_leaf_t *bihleaf;
11080 float vertex3f[3][3];
11081 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11083 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11085 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11087 switch (bihleaf->type)
11090 brush = model->brush.data_brushes + bihleaf->itemindex;
11091 if (brush->colbrushf && brush->colbrushf->numtriangles)
11093 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);
11094 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11095 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11098 case BIH_COLLISIONTRIANGLE:
11099 triangleindex = bihleaf->itemindex;
11100 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11101 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11102 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11103 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);
11104 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11105 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11107 case BIH_RENDERTRIANGLE:
11108 triangleindex = bihleaf->itemindex;
11109 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11110 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11111 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11112 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);
11113 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11114 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11120 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11122 if (r_showtris.integer && qglPolygonMode)
11124 if (r_showdisabledepthtest.integer)
11126 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11127 GL_DepthMask(false);
11131 GL_BlendFunc(GL_ONE, GL_ZERO);
11132 GL_DepthMask(true);
11134 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11135 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11137 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11139 rsurface.texture = R_GetCurrentTexture(surface->texture);
11140 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11142 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11143 if (!rsurface.texture->currentlayers->depthmask)
11144 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11145 else if (ent == r_refdef.scene.worldentity)
11146 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11148 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11149 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11153 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11154 rsurface.texture = NULL;
11157 if (r_shownormals.value != 0 && qglBegin)
11159 if (r_showdisabledepthtest.integer)
11161 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11162 GL_DepthMask(false);
11166 GL_BlendFunc(GL_ONE, GL_ZERO);
11167 GL_DepthMask(true);
11169 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11171 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11173 rsurface.texture = R_GetCurrentTexture(surface->texture);
11174 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11176 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11177 qglBegin(GL_LINES);
11178 if (r_shownormals.value < 0)
11180 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11182 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11183 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11184 qglVertex3f(v[0], v[1], v[2]);
11185 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11186 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11187 qglVertex3f(v[0], v[1], v[2]);
11190 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11192 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11194 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11195 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11196 qglVertex3f(v[0], v[1], v[2]);
11197 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11198 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11199 qglVertex3f(v[0], v[1], v[2]);
11201 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11203 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11204 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11205 qglVertex3f(v[0], v[1], v[2]);
11206 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11207 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11208 qglVertex3f(v[0], v[1], v[2]);
11210 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11212 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11213 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11214 qglVertex3f(v[0], v[1], v[2]);
11215 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11216 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11217 qglVertex3f(v[0], v[1], v[2]);
11224 rsurface.texture = NULL;
11228 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11229 int r_maxsurfacelist = 0;
11230 const msurface_t **r_surfacelist = NULL;
11231 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11233 int i, j, endj, flagsmask;
11234 dp_model_t *model = r_refdef.scene.worldmodel;
11235 msurface_t *surfaces;
11236 unsigned char *update;
11237 int numsurfacelist = 0;
11241 if (r_maxsurfacelist < model->num_surfaces)
11243 r_maxsurfacelist = model->num_surfaces;
11245 Mem_Free((msurface_t**)r_surfacelist);
11246 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11249 RSurf_ActiveWorldEntity();
11251 surfaces = model->data_surfaces;
11252 update = model->brushq1.lightmapupdateflags;
11254 // update light styles on this submodel
11255 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11257 model_brush_lightstyleinfo_t *style;
11258 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11260 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11262 int *list = style->surfacelist;
11263 style->value = r_refdef.scene.lightstylevalue[style->style];
11264 for (j = 0;j < style->numsurfaces;j++)
11265 update[list[j]] = true;
11270 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11274 R_DrawDebugModel();
11275 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11279 rsurface.lightmaptexture = NULL;
11280 rsurface.deluxemaptexture = NULL;
11281 rsurface.uselightmaptexture = false;
11282 rsurface.texture = NULL;
11283 rsurface.rtlight = NULL;
11284 numsurfacelist = 0;
11285 // add visible surfaces to draw list
11286 for (i = 0;i < model->nummodelsurfaces;i++)
11288 j = model->sortedmodelsurfaces[i];
11289 if (r_refdef.viewcache.world_surfacevisible[j])
11290 r_surfacelist[numsurfacelist++] = surfaces + j;
11292 // update lightmaps if needed
11293 if (model->brushq1.firstrender)
11295 model->brushq1.firstrender = false;
11296 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11298 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11302 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11303 if (r_refdef.viewcache.world_surfacevisible[j])
11305 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11307 // don't do anything if there were no surfaces
11308 if (!numsurfacelist)
11310 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11313 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11315 // add to stats if desired
11316 if (r_speeds.integer && !skysurfaces && !depthonly)
11318 r_refdef.stats.world_surfaces += numsurfacelist;
11319 for (j = 0;j < numsurfacelist;j++)
11320 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11323 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11326 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11328 int i, j, endj, flagsmask;
11329 dp_model_t *model = ent->model;
11330 msurface_t *surfaces;
11331 unsigned char *update;
11332 int numsurfacelist = 0;
11336 if (r_maxsurfacelist < model->num_surfaces)
11338 r_maxsurfacelist = model->num_surfaces;
11340 Mem_Free((msurface_t **)r_surfacelist);
11341 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11344 // if the model is static it doesn't matter what value we give for
11345 // wantnormals and wanttangents, so this logic uses only rules applicable
11346 // to a model, knowing that they are meaningless otherwise
11347 if (ent == r_refdef.scene.worldentity)
11348 RSurf_ActiveWorldEntity();
11349 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11350 RSurf_ActiveModelEntity(ent, false, false, false);
11352 RSurf_ActiveModelEntity(ent, true, true, true);
11353 else if (depthonly)
11355 switch (vid.renderpath)
11357 case RENDERPATH_GL20:
11358 case RENDERPATH_D3D9:
11359 case RENDERPATH_D3D10:
11360 case RENDERPATH_D3D11:
11361 case RENDERPATH_SOFT:
11362 case RENDERPATH_GLES2:
11363 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11365 case RENDERPATH_GL11:
11366 case RENDERPATH_GL13:
11367 case RENDERPATH_GLES1:
11368 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11374 switch (vid.renderpath)
11376 case RENDERPATH_GL20:
11377 case RENDERPATH_D3D9:
11378 case RENDERPATH_D3D10:
11379 case RENDERPATH_D3D11:
11380 case RENDERPATH_SOFT:
11381 case RENDERPATH_GLES2:
11382 RSurf_ActiveModelEntity(ent, true, true, false);
11384 case RENDERPATH_GL11:
11385 case RENDERPATH_GL13:
11386 case RENDERPATH_GLES1:
11387 RSurf_ActiveModelEntity(ent, true, false, false);
11392 surfaces = model->data_surfaces;
11393 update = model->brushq1.lightmapupdateflags;
11395 // update light styles
11396 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11398 model_brush_lightstyleinfo_t *style;
11399 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11401 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11403 int *list = style->surfacelist;
11404 style->value = r_refdef.scene.lightstylevalue[style->style];
11405 for (j = 0;j < style->numsurfaces;j++)
11406 update[list[j]] = true;
11411 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11415 R_DrawDebugModel();
11416 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11420 rsurface.lightmaptexture = NULL;
11421 rsurface.deluxemaptexture = NULL;
11422 rsurface.uselightmaptexture = false;
11423 rsurface.texture = NULL;
11424 rsurface.rtlight = NULL;
11425 numsurfacelist = 0;
11426 // add visible surfaces to draw list
11427 for (i = 0;i < model->nummodelsurfaces;i++)
11428 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11429 // don't do anything if there were no surfaces
11430 if (!numsurfacelist)
11432 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11435 // update lightmaps if needed
11439 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11444 R_BuildLightMap(ent, surfaces + j);
11449 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11451 R_BuildLightMap(ent, surfaces + j);
11452 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11454 // add to stats if desired
11455 if (r_speeds.integer && !skysurfaces && !depthonly)
11457 r_refdef.stats.entities_surfaces += numsurfacelist;
11458 for (j = 0;j < numsurfacelist;j++)
11459 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11462 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11465 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11467 static texture_t texture;
11468 static msurface_t surface;
11469 const msurface_t *surfacelist = &surface;
11471 // fake enough texture and surface state to render this geometry
11473 texture.update_lastrenderframe = -1; // regenerate this texture
11474 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11475 texture.currentskinframe = skinframe;
11476 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11477 texture.offsetmapping = OFFSETMAPPING_OFF;
11478 texture.offsetscale = 1;
11479 texture.specularscalemod = 1;
11480 texture.specularpowermod = 1;
11482 surface.texture = &texture;
11483 surface.num_triangles = numtriangles;
11484 surface.num_firsttriangle = firsttriangle;
11485 surface.num_vertices = numvertices;
11486 surface.num_firstvertex = firstvertex;
11489 rsurface.texture = R_GetCurrentTexture(surface.texture);
11490 rsurface.lightmaptexture = NULL;
11491 rsurface.deluxemaptexture = NULL;
11492 rsurface.uselightmaptexture = false;
11493 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11496 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)
11498 static msurface_t surface;
11499 const msurface_t *surfacelist = &surface;
11501 // fake enough texture and surface state to render this geometry
11502 surface.texture = texture;
11503 surface.num_triangles = numtriangles;
11504 surface.num_firsttriangle = firsttriangle;
11505 surface.num_vertices = numvertices;
11506 surface.num_firstvertex = firstvertex;
11509 rsurface.texture = R_GetCurrentTexture(surface.texture);
11510 rsurface.lightmaptexture = NULL;
11511 rsurface.deluxemaptexture = NULL;
11512 rsurface.uselightmaptexture = false;
11513 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);