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)
2096 permutation |= SHADERPERMUTATION_ALPHAKILL;
2100 GL_AlphaTest(false);
2101 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2102 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2103 if (rsurfacepass == RSURFPASS_BACKGROUND)
2105 // distorted background
2106 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2108 mode = SHADERMODE_WATER;
2109 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2111 // this is the right thing to do for wateralpha
2112 GL_BlendFunc(GL_ONE, GL_ZERO);
2113 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2117 // this is the right thing to do for entity alpha
2118 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2119 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2122 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2124 mode = SHADERMODE_REFRACTION;
2125 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2126 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2130 mode = SHADERMODE_GENERIC;
2131 permutation |= SHADERPERMUTATION_DIFFUSE;
2132 GL_BlendFunc(GL_ONE, GL_ZERO);
2133 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2136 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2138 if (r_glsl_offsetmapping.integer)
2140 switch(rsurface.texture->offsetmapping)
2142 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2143 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2144 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2145 case OFFSETMAPPING_OFF: break;
2148 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2149 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2150 // normalmap (deferred prepass), may use alpha test on diffuse
2151 mode = SHADERMODE_DEFERREDGEOMETRY;
2152 GL_BlendFunc(GL_ONE, GL_ZERO);
2153 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2155 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2157 if (r_glsl_offsetmapping.integer)
2159 switch(rsurface.texture->offsetmapping)
2161 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2162 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2163 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2164 case OFFSETMAPPING_OFF: break;
2167 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2168 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2170 mode = SHADERMODE_LIGHTSOURCE;
2171 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2172 permutation |= SHADERPERMUTATION_CUBEFILTER;
2173 if (diffusescale > 0)
2174 permutation |= SHADERPERMUTATION_DIFFUSE;
2175 if (specularscale > 0)
2176 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2177 if (r_refdef.fogenabled)
2178 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2179 if (rsurface.texture->colormapping)
2180 permutation |= SHADERPERMUTATION_COLORMAPPING;
2181 if (r_shadow_usingshadowmap2d)
2183 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2184 if(r_shadow_shadowmapvsdct)
2185 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2187 if (r_shadow_shadowmapsampler)
2188 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2189 if (r_shadow_shadowmappcf > 1)
2190 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2191 else if (r_shadow_shadowmappcf)
2192 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2194 if (rsurface.texture->reflectmasktexture)
2195 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2196 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2197 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2199 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2201 if (r_glsl_offsetmapping.integer)
2203 switch(rsurface.texture->offsetmapping)
2205 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2206 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2207 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2208 case OFFSETMAPPING_OFF: break;
2211 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2212 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2213 // unshaded geometry (fullbright or ambient model lighting)
2214 mode = SHADERMODE_FLATCOLOR;
2215 ambientscale = diffusescale = specularscale = 0;
2216 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2217 permutation |= SHADERPERMUTATION_GLOW;
2218 if (r_refdef.fogenabled)
2219 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2220 if (rsurface.texture->colormapping)
2221 permutation |= SHADERPERMUTATION_COLORMAPPING;
2222 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2224 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2225 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2227 if (r_shadow_shadowmapsampler)
2228 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2229 if (r_shadow_shadowmappcf > 1)
2230 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2231 else if (r_shadow_shadowmappcf)
2232 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2234 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2235 permutation |= SHADERPERMUTATION_REFLECTION;
2236 if (rsurface.texture->reflectmasktexture)
2237 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2238 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2239 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2241 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2243 if (r_glsl_offsetmapping.integer)
2245 switch(rsurface.texture->offsetmapping)
2247 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2248 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2249 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2250 case OFFSETMAPPING_OFF: break;
2253 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2254 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2255 // directional model lighting
2256 mode = SHADERMODE_LIGHTDIRECTION;
2257 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2258 permutation |= SHADERPERMUTATION_GLOW;
2259 permutation |= SHADERPERMUTATION_DIFFUSE;
2260 if (specularscale > 0)
2261 permutation |= SHADERPERMUTATION_SPECULAR;
2262 if (r_refdef.fogenabled)
2263 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2264 if (rsurface.texture->colormapping)
2265 permutation |= SHADERPERMUTATION_COLORMAPPING;
2266 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2268 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2269 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2271 if (r_shadow_shadowmapsampler)
2272 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2273 if (r_shadow_shadowmappcf > 1)
2274 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2275 else if (r_shadow_shadowmappcf)
2276 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2278 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2279 permutation |= SHADERPERMUTATION_REFLECTION;
2280 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2281 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2282 if (rsurface.texture->reflectmasktexture)
2283 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2284 if (r_shadow_bouncegridtexture)
2286 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2287 if (r_shadow_bouncegriddirectional)
2288 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2290 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2291 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2293 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2295 if (r_glsl_offsetmapping.integer)
2297 switch(rsurface.texture->offsetmapping)
2299 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2300 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2301 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2302 case OFFSETMAPPING_OFF: break;
2305 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2306 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2307 // ambient model lighting
2308 mode = SHADERMODE_LIGHTDIRECTION;
2309 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2310 permutation |= SHADERPERMUTATION_GLOW;
2311 if (r_refdef.fogenabled)
2312 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2313 if (rsurface.texture->colormapping)
2314 permutation |= SHADERPERMUTATION_COLORMAPPING;
2315 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2317 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2318 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2320 if (r_shadow_shadowmapsampler)
2321 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2322 if (r_shadow_shadowmappcf > 1)
2323 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2324 else if (r_shadow_shadowmappcf)
2325 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2327 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2328 permutation |= SHADERPERMUTATION_REFLECTION;
2329 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2330 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2331 if (rsurface.texture->reflectmasktexture)
2332 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2333 if (r_shadow_bouncegridtexture)
2335 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2336 if (r_shadow_bouncegriddirectional)
2337 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2339 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2340 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2344 if (r_glsl_offsetmapping.integer)
2346 switch(rsurface.texture->offsetmapping)
2348 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2349 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2350 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2351 case OFFSETMAPPING_OFF: break;
2354 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2355 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2357 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2358 permutation |= SHADERPERMUTATION_GLOW;
2359 if (r_refdef.fogenabled)
2360 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2361 if (rsurface.texture->colormapping)
2362 permutation |= SHADERPERMUTATION_COLORMAPPING;
2363 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2365 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2366 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2368 if (r_shadow_shadowmapsampler)
2369 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2370 if (r_shadow_shadowmappcf > 1)
2371 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2372 else if (r_shadow_shadowmappcf)
2373 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2375 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2376 permutation |= SHADERPERMUTATION_REFLECTION;
2377 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2378 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2379 if (rsurface.texture->reflectmasktexture)
2380 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2381 if (FAKELIGHT_ENABLED)
2383 // fake lightmapping (q1bsp, q3bsp, fullbright map)
2384 mode = SHADERMODE_FAKELIGHT;
2385 permutation |= SHADERPERMUTATION_DIFFUSE;
2386 if (specularscale > 0)
2387 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2389 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2391 // deluxemapping (light direction texture)
2392 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2393 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2395 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2396 permutation |= SHADERPERMUTATION_DIFFUSE;
2397 if (specularscale > 0)
2398 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2400 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2402 // fake deluxemapping (uniform light direction in tangentspace)
2403 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2404 permutation |= SHADERPERMUTATION_DIFFUSE;
2405 if (specularscale > 0)
2406 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2408 else if (rsurface.uselightmaptexture)
2410 // ordinary lightmapping (q1bsp, q3bsp)
2411 mode = SHADERMODE_LIGHTMAP;
2415 // ordinary vertex coloring (q3bsp)
2416 mode = SHADERMODE_VERTEXCOLOR;
2418 if (r_shadow_bouncegridtexture)
2420 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2421 if (r_shadow_bouncegriddirectional)
2422 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2424 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2425 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2427 if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2428 colormod = dummy_colormod;
2429 if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2430 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2431 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2432 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2433 switch(vid.renderpath)
2435 case RENDERPATH_D3D9:
2437 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);
2438 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2439 R_SetupShader_SetPermutationHLSL(mode, permutation);
2440 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2441 if (mode == SHADERMODE_LIGHTSOURCE)
2443 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2444 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2448 if (mode == SHADERMODE_LIGHTDIRECTION)
2450 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2453 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2454 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2455 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2456 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2457 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2459 if (mode == SHADERMODE_LIGHTSOURCE)
2461 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2462 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2463 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2464 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2465 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2467 // additive passes are only darkened by fog, not tinted
2468 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2469 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2473 if (mode == SHADERMODE_FLATCOLOR)
2475 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2477 else if (mode == SHADERMODE_LIGHTDIRECTION)
2479 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]);
2480 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2481 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);
2482 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);
2483 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2484 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2485 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2489 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2490 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2491 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);
2492 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);
2493 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2495 // additive passes are only darkened by fog, not tinted
2496 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2497 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2499 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2500 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);
2501 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2502 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2503 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2504 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2505 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2506 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2507 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2508 if (mode == SHADERMODE_WATER)
2509 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2511 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2512 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2513 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2514 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));
2515 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2516 if (rsurface.texture->pantstexture)
2517 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2519 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2520 if (rsurface.texture->shirttexture)
2521 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2523 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2524 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2525 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2526 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2527 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2528 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2529 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2530 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2531 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2532 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2534 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2535 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2537 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2538 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2539 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2540 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2541 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2542 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2543 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2544 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2545 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2546 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2547 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2548 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2549 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2550 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2551 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2552 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2553 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2554 if (rsurfacepass == RSURFPASS_BACKGROUND)
2556 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2557 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2558 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2562 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2564 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2565 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2566 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2567 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2568 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2570 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2571 if (rsurface.rtlight)
2573 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2574 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2579 case RENDERPATH_D3D10:
2580 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2582 case RENDERPATH_D3D11:
2583 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2585 case RENDERPATH_GL20:
2586 case RENDERPATH_GLES2:
2587 if (!vid.useinterleavedarrays)
2589 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);
2590 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2591 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2592 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2593 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2594 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2595 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2596 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2600 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);
2601 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2603 R_SetupShader_SetPermutationGLSL(mode, permutation);
2604 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2605 if (mode == SHADERMODE_LIGHTSOURCE)
2607 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2608 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2609 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2610 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2611 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2612 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);
2614 // additive passes are only darkened by fog, not tinted
2615 if (r_glsl_permutation->loc_FogColor >= 0)
2616 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2617 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2621 if (mode == SHADERMODE_FLATCOLOR)
2623 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2625 else if (mode == SHADERMODE_LIGHTDIRECTION)
2627 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]);
2628 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]);
2629 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);
2630 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);
2631 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);
2632 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]);
2633 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]);
2637 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]);
2638 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]);
2639 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);
2640 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);
2641 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);
2643 // additive passes are only darkened by fog, not tinted
2644 if (r_glsl_permutation->loc_FogColor >= 0)
2646 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2647 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2649 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2651 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);
2652 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]);
2653 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]);
2654 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]);
2655 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]);
2656 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2657 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2658 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2659 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]);
2661 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2662 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2663 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2664 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]);
2665 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]);
2667 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2668 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));
2669 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2670 if (r_glsl_permutation->loc_Color_Pants >= 0)
2672 if (rsurface.texture->pantstexture)
2673 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2675 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2677 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2679 if (rsurface.texture->shirttexture)
2680 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2682 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2684 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]);
2685 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2686 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2687 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2688 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2689 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2690 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2691 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2692 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2694 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]);
2695 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2696 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);}
2697 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2699 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
2700 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
2701 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
2702 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
2703 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
2704 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
2705 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
2706 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
2707 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
2708 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
2709 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
2710 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
2711 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
2712 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
2713 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);
2714 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
2715 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
2716 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2717 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2718 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2719 if (rsurfacepass == RSURFPASS_BACKGROUND)
2721 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);
2722 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);
2723 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);
2727 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);
2729 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2730 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2731 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
2732 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
2733 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2735 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture );
2736 if (rsurface.rtlight)
2738 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2739 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2742 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2745 case RENDERPATH_GL11:
2746 case RENDERPATH_GL13:
2747 case RENDERPATH_GLES1:
2749 case RENDERPATH_SOFT:
2750 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);
2751 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2752 R_SetupShader_SetPermutationSoft(mode, permutation);
2753 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2754 if (mode == SHADERMODE_LIGHTSOURCE)
2756 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2757 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2758 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2759 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2760 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2761 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2763 // additive passes are only darkened by fog, not tinted
2764 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2765 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2769 if (mode == SHADERMODE_FLATCOLOR)
2771 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2773 else if (mode == SHADERMODE_LIGHTDIRECTION)
2775 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]);
2776 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2777 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);
2778 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);
2779 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2780 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]);
2781 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2785 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2786 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2787 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);
2788 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);
2789 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2791 // additive passes are only darkened by fog, not tinted
2792 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2793 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2795 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2796 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);
2797 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2798 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2799 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]);
2800 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]);
2801 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2802 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2803 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2804 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2806 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2807 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2808 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2809 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2810 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]);
2812 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2813 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));
2814 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2815 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2817 if (rsurface.texture->pantstexture)
2818 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2820 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2822 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2824 if (rsurface.texture->shirttexture)
2825 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2827 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2829 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2830 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2831 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2832 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2833 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2834 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2835 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2836 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2837 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2839 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2840 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2842 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2843 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2844 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2845 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2846 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2847 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2848 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2849 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2850 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2851 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2852 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2853 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2854 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2855 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2856 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2857 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2858 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2859 if (rsurfacepass == RSURFPASS_BACKGROUND)
2861 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2862 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2863 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2867 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2869 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2870 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2871 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2872 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2873 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2875 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2876 if (rsurface.rtlight)
2878 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2879 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2886 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2888 // select a permutation of the lighting shader appropriate to this
2889 // combination of texture, entity, light source, and fogging, only use the
2890 // minimum features necessary to avoid wasting rendering time in the
2891 // fragment shader on features that are not being used
2892 unsigned int permutation = 0;
2893 unsigned int mode = 0;
2894 const float *lightcolorbase = rtlight->currentcolor;
2895 float ambientscale = rtlight->ambientscale;
2896 float diffusescale = rtlight->diffusescale;
2897 float specularscale = rtlight->specularscale;
2898 // this is the location of the light in view space
2899 vec3_t viewlightorigin;
2900 // this transforms from view space (camera) to light space (cubemap)
2901 matrix4x4_t viewtolight;
2902 matrix4x4_t lighttoview;
2903 float viewtolight16f[16];
2904 float range = 1.0f / r_shadow_deferred_8bitrange.value;
2906 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2907 if (rtlight->currentcubemap != r_texture_whitecube)
2908 permutation |= SHADERPERMUTATION_CUBEFILTER;
2909 if (diffusescale > 0)
2910 permutation |= SHADERPERMUTATION_DIFFUSE;
2911 if (specularscale > 0 && r_shadow_gloss.integer > 0)
2912 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2913 if (r_shadow_usingshadowmap2d)
2915 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2916 if (r_shadow_shadowmapvsdct)
2917 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2919 if (r_shadow_shadowmapsampler)
2920 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2921 if (r_shadow_shadowmappcf > 1)
2922 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2923 else if (r_shadow_shadowmappcf)
2924 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2926 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2927 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2928 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2929 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2930 switch(vid.renderpath)
2932 case RENDERPATH_D3D9:
2934 R_SetupShader_SetPermutationHLSL(mode, permutation);
2935 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2936 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
2937 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2938 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2939 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2940 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2941 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2942 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2943 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2944 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2946 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2947 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthcolortexture );
2948 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2949 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2950 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dcolortexture );
2951 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2954 case RENDERPATH_D3D10:
2955 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2957 case RENDERPATH_D3D11:
2958 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2960 case RENDERPATH_GL20:
2961 case RENDERPATH_GLES2:
2962 R_SetupShader_SetPermutationGLSL(mode, permutation);
2963 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2964 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
2965 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);
2966 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);
2967 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);
2968 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]);
2969 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]);
2970 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));
2971 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]);
2972 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
2974 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2975 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2976 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2977 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2978 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );
2979 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2981 case RENDERPATH_GL11:
2982 case RENDERPATH_GL13:
2983 case RENDERPATH_GLES1:
2985 case RENDERPATH_SOFT:
2986 R_SetupShader_SetPermutationGLSL(mode, permutation);
2987 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2988 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
2989 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2990 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2991 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2992 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2993 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]);
2994 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));
2995 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2996 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2998 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2999 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
3000 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3001 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3002 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
3003 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3008 #define SKINFRAME_HASH 1024
3012 int loadsequence; // incremented each level change
3013 memexpandablearray_t array;
3014 skinframe_t *hash[SKINFRAME_HASH];
3017 r_skinframe_t r_skinframe;
3019 void R_SkinFrame_PrepareForPurge(void)
3021 r_skinframe.loadsequence++;
3022 // wrap it without hitting zero
3023 if (r_skinframe.loadsequence >= 200)
3024 r_skinframe.loadsequence = 1;
3027 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3031 // mark the skinframe as used for the purging code
3032 skinframe->loadsequence = r_skinframe.loadsequence;
3035 void R_SkinFrame_Purge(void)
3039 for (i = 0;i < SKINFRAME_HASH;i++)
3041 for (s = r_skinframe.hash[i];s;s = s->next)
3043 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3045 if (s->merged == s->base)
3047 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3048 R_PurgeTexture(s->stain );s->stain = NULL;
3049 R_PurgeTexture(s->merged);s->merged = NULL;
3050 R_PurgeTexture(s->base );s->base = NULL;
3051 R_PurgeTexture(s->pants );s->pants = NULL;
3052 R_PurgeTexture(s->shirt );s->shirt = NULL;
3053 R_PurgeTexture(s->nmap );s->nmap = NULL;
3054 R_PurgeTexture(s->gloss );s->gloss = NULL;
3055 R_PurgeTexture(s->glow );s->glow = NULL;
3056 R_PurgeTexture(s->fog );s->fog = NULL;
3057 R_PurgeTexture(s->reflect);s->reflect = NULL;
3058 s->loadsequence = 0;
3064 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3066 char basename[MAX_QPATH];
3068 Image_StripImageExtension(name, basename, sizeof(basename));
3070 if( last == NULL ) {
3072 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3073 item = r_skinframe.hash[hashindex];
3078 // linearly search through the hash bucket
3079 for( ; item ; item = item->next ) {
3080 if( !strcmp( item->basename, basename ) ) {
3087 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3091 char basename[MAX_QPATH];
3093 Image_StripImageExtension(name, basename, sizeof(basename));
3095 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3096 for (item = r_skinframe.hash[hashindex];item;item = item->next)
3097 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3101 rtexture_t *dyntexture;
3102 // check whether its a dynamic texture
3103 dyntexture = CL_GetDynTexture( basename );
3104 if (!add && !dyntexture)
3106 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3107 memset(item, 0, sizeof(*item));
3108 strlcpy(item->basename, basename, sizeof(item->basename));
3109 item->base = dyntexture; // either NULL or dyntexture handle
3110 item->textureflags = textureflags;
3111 item->comparewidth = comparewidth;
3112 item->compareheight = compareheight;
3113 item->comparecrc = comparecrc;
3114 item->next = r_skinframe.hash[hashindex];
3115 r_skinframe.hash[hashindex] = item;
3117 else if( item->base == NULL )
3119 rtexture_t *dyntexture;
3120 // check whether its a dynamic texture
3121 // 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]
3122 dyntexture = CL_GetDynTexture( basename );
3123 item->base = dyntexture; // either NULL or dyntexture handle
3126 R_SkinFrame_MarkUsed(item);
3130 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3132 unsigned long long avgcolor[5], wsum; \
3140 for(pix = 0; pix < cnt; ++pix) \
3143 for(comp = 0; comp < 3; ++comp) \
3145 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3148 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3150 for(comp = 0; comp < 3; ++comp) \
3151 avgcolor[comp] += getpixel * w; \
3154 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3155 avgcolor[4] += getpixel; \
3157 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3159 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3160 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3161 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3162 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3165 extern cvar_t gl_picmip;
3166 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3169 unsigned char *pixels;
3170 unsigned char *bumppixels;
3171 unsigned char *basepixels = NULL;
3172 int basepixels_width = 0;
3173 int basepixels_height = 0;
3174 skinframe_t *skinframe;
3175 rtexture_t *ddsbase = NULL;
3176 qboolean ddshasalpha = false;
3177 float ddsavgcolor[4];
3178 char basename[MAX_QPATH];
3179 int miplevel = R_PicmipForFlags(textureflags);
3180 int savemiplevel = miplevel;
3183 if (cls.state == ca_dedicated)
3186 // return an existing skinframe if already loaded
3187 // if loading of the first image fails, don't make a new skinframe as it
3188 // would cause all future lookups of this to be missing
3189 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3190 if (skinframe && skinframe->base)
3193 Image_StripImageExtension(name, basename, sizeof(basename));
3195 // check for DDS texture file first
3196 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3198 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3199 if (basepixels == NULL)
3203 // FIXME handle miplevel
3205 if (developer_loading.integer)
3206 Con_Printf("loading skin \"%s\"\n", name);
3208 // we've got some pixels to store, so really allocate this new texture now
3210 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3211 skinframe->stain = NULL;
3212 skinframe->merged = NULL;
3213 skinframe->base = NULL;
3214 skinframe->pants = NULL;
3215 skinframe->shirt = NULL;
3216 skinframe->nmap = NULL;
3217 skinframe->gloss = NULL;
3218 skinframe->glow = NULL;
3219 skinframe->fog = NULL;
3220 skinframe->reflect = NULL;
3221 skinframe->hasalpha = false;
3225 skinframe->base = ddsbase;
3226 skinframe->hasalpha = ddshasalpha;
3227 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3228 if (r_loadfog && skinframe->hasalpha)
3229 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3230 //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]);
3234 basepixels_width = image_width;
3235 basepixels_height = image_height;
3236 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);
3237 if (textureflags & TEXF_ALPHA)
3239 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3241 if (basepixels[j] < 255)
3243 skinframe->hasalpha = true;
3247 if (r_loadfog && skinframe->hasalpha)
3249 // has transparent pixels
3250 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3251 for (j = 0;j < image_width * image_height * 4;j += 4)
3256 pixels[j+3] = basepixels[j+3];
3258 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);
3262 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3263 //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]);
3264 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3265 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3266 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3267 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3272 mymiplevel = savemiplevel;
3273 if (r_loadnormalmap)
3274 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);
3275 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3277 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3278 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3279 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3280 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3283 // _norm is the name used by tenebrae and has been adopted as standard
3284 if (r_loadnormalmap && skinframe->nmap == NULL)
3286 mymiplevel = savemiplevel;
3287 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3289 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);
3293 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3295 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3296 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3297 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);
3299 Mem_Free(bumppixels);
3301 else if (r_shadow_bumpscale_basetexture.value > 0)
3303 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3304 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3305 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);
3308 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3309 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3312 // _luma is supported only for tenebrae compatibility
3313 // _glow is the preferred name
3314 mymiplevel = savemiplevel;
3315 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))))
3317 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);
3318 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3319 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3320 Mem_Free(pixels);pixels = NULL;
3323 mymiplevel = savemiplevel;
3324 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3326 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);
3327 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3328 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3333 mymiplevel = savemiplevel;
3334 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3336 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);
3337 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3338 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3343 mymiplevel = savemiplevel;
3344 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3346 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);
3347 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3348 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3353 mymiplevel = savemiplevel;
3354 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3356 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);
3357 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3358 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3364 Mem_Free(basepixels);
3369 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3370 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3373 unsigned char *temp1, *temp2;
3374 skinframe_t *skinframe;
3376 if (cls.state == ca_dedicated)
3379 // if already loaded just return it, otherwise make a new skinframe
3380 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3381 if (skinframe && skinframe->base)
3384 skinframe->stain = NULL;
3385 skinframe->merged = NULL;
3386 skinframe->base = NULL;
3387 skinframe->pants = NULL;
3388 skinframe->shirt = NULL;
3389 skinframe->nmap = NULL;
3390 skinframe->gloss = NULL;
3391 skinframe->glow = NULL;
3392 skinframe->fog = NULL;
3393 skinframe->reflect = NULL;
3394 skinframe->hasalpha = false;
3396 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3400 if (developer_loading.integer)
3401 Con_Printf("loading 32bit skin \"%s\"\n", name);
3403 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3405 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3406 temp2 = temp1 + width * height * 4;
3407 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3408 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);
3411 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3412 if (textureflags & TEXF_ALPHA)
3414 for (i = 3;i < width * height * 4;i += 4)
3416 if (skindata[i] < 255)
3418 skinframe->hasalpha = true;
3422 if (r_loadfog && skinframe->hasalpha)
3424 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3425 memcpy(fogpixels, skindata, width * height * 4);
3426 for (i = 0;i < width * height * 4;i += 4)
3427 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3428 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3429 Mem_Free(fogpixels);
3433 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3434 //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]);
3439 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3443 skinframe_t *skinframe;
3445 if (cls.state == ca_dedicated)
3448 // if already loaded just return it, otherwise make a new skinframe
3449 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3450 if (skinframe && skinframe->base)
3453 skinframe->stain = NULL;
3454 skinframe->merged = NULL;
3455 skinframe->base = NULL;
3456 skinframe->pants = NULL;
3457 skinframe->shirt = NULL;
3458 skinframe->nmap = NULL;
3459 skinframe->gloss = NULL;
3460 skinframe->glow = NULL;
3461 skinframe->fog = NULL;
3462 skinframe->reflect = NULL;
3463 skinframe->hasalpha = false;
3465 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3469 if (developer_loading.integer)
3470 Con_Printf("loading quake skin \"%s\"\n", name);
3472 // 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)
3473 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3474 memcpy(skinframe->qpixels, skindata, width*height);
3475 skinframe->qwidth = width;
3476 skinframe->qheight = height;
3479 for (i = 0;i < width * height;i++)
3480 featuresmask |= palette_featureflags[skindata[i]];
3482 skinframe->hasalpha = false;
3483 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3484 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3485 skinframe->qgeneratemerged = true;
3486 skinframe->qgeneratebase = skinframe->qhascolormapping;
3487 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3489 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3490 //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]);
3495 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3499 unsigned char *skindata;
3501 if (!skinframe->qpixels)
3504 if (!skinframe->qhascolormapping)
3505 colormapped = false;
3509 if (!skinframe->qgeneratebase)
3514 if (!skinframe->qgeneratemerged)
3518 width = skinframe->qwidth;
3519 height = skinframe->qheight;
3520 skindata = skinframe->qpixels;
3522 if (skinframe->qgeneratenmap)
3524 unsigned char *temp1, *temp2;
3525 skinframe->qgeneratenmap = false;
3526 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3527 temp2 = temp1 + width * height * 4;
3528 // use either a custom palette or the quake palette
3529 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3530 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3531 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);
3535 if (skinframe->qgenerateglow)
3537 skinframe->qgenerateglow = false;
3538 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
3543 skinframe->qgeneratebase = false;
3544 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);
3545 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);
3546 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);
3550 skinframe->qgeneratemerged = false;
3551 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);
3554 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3556 Mem_Free(skinframe->qpixels);
3557 skinframe->qpixels = NULL;
3561 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)
3564 skinframe_t *skinframe;
3566 if (cls.state == ca_dedicated)
3569 // if already loaded just return it, otherwise make a new skinframe
3570 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3571 if (skinframe && skinframe->base)
3574 skinframe->stain = NULL;
3575 skinframe->merged = NULL;
3576 skinframe->base = NULL;
3577 skinframe->pants = NULL;
3578 skinframe->shirt = NULL;
3579 skinframe->nmap = NULL;
3580 skinframe->gloss = NULL;
3581 skinframe->glow = NULL;
3582 skinframe->fog = NULL;
3583 skinframe->reflect = NULL;
3584 skinframe->hasalpha = false;
3586 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3590 if (developer_loading.integer)
3591 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3593 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3594 if (textureflags & TEXF_ALPHA)
3596 for (i = 0;i < width * height;i++)
3598 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3600 skinframe->hasalpha = true;
3604 if (r_loadfog && skinframe->hasalpha)
3605 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3608 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3609 //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]);
3614 skinframe_t *R_SkinFrame_LoadMissing(void)
3616 skinframe_t *skinframe;
3618 if (cls.state == ca_dedicated)
3621 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3622 skinframe->stain = NULL;
3623 skinframe->merged = NULL;
3624 skinframe->base = NULL;
3625 skinframe->pants = NULL;
3626 skinframe->shirt = NULL;
3627 skinframe->nmap = NULL;
3628 skinframe->gloss = NULL;
3629 skinframe->glow = NULL;
3630 skinframe->fog = NULL;
3631 skinframe->reflect = NULL;
3632 skinframe->hasalpha = false;
3634 skinframe->avgcolor[0] = rand() / RAND_MAX;
3635 skinframe->avgcolor[1] = rand() / RAND_MAX;
3636 skinframe->avgcolor[2] = rand() / RAND_MAX;
3637 skinframe->avgcolor[3] = 1;
3642 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3643 typedef struct suffixinfo_s
3646 qboolean flipx, flipy, flipdiagonal;
3649 static suffixinfo_t suffix[3][6] =
3652 {"px", false, false, false},
3653 {"nx", false, false, false},
3654 {"py", false, false, false},
3655 {"ny", false, false, false},
3656 {"pz", false, false, false},
3657 {"nz", false, false, false}
3660 {"posx", false, false, false},
3661 {"negx", false, false, false},
3662 {"posy", false, false, false},
3663 {"negy", false, false, false},
3664 {"posz", false, false, false},
3665 {"negz", false, false, false}
3668 {"rt", true, false, true},
3669 {"lf", false, true, true},
3670 {"ft", true, true, false},
3671 {"bk", false, false, false},
3672 {"up", true, false, true},
3673 {"dn", true, false, true}
3677 static int componentorder[4] = {0, 1, 2, 3};
3679 rtexture_t *R_LoadCubemap(const char *basename)
3681 int i, j, cubemapsize;
3682 unsigned char *cubemappixels, *image_buffer;
3683 rtexture_t *cubemaptexture;
3685 // must start 0 so the first loadimagepixels has no requested width/height
3687 cubemappixels = NULL;
3688 cubemaptexture = NULL;
3689 // keep trying different suffix groups (posx, px, rt) until one loads
3690 for (j = 0;j < 3 && !cubemappixels;j++)
3692 // load the 6 images in the suffix group
3693 for (i = 0;i < 6;i++)
3695 // generate an image name based on the base and and suffix
3696 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3698 if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3700 // an image loaded, make sure width and height are equal
3701 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3703 // if this is the first image to load successfully, allocate the cubemap memory
3704 if (!cubemappixels && image_width >= 1)
3706 cubemapsize = image_width;
3707 // note this clears to black, so unavailable sides are black
3708 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3710 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3712 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);
3715 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3717 Mem_Free(image_buffer);
3721 // if a cubemap loaded, upload it
3724 if (developer_loading.integer)
3725 Con_Printf("loading cubemap \"%s\"\n", basename);
3727 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);
3728 Mem_Free(cubemappixels);
3732 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3733 if (developer_loading.integer)
3735 Con_Printf("(tried tried images ");
3736 for (j = 0;j < 3;j++)
3737 for (i = 0;i < 6;i++)
3738 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3739 Con_Print(" and was unable to find any of them).\n");
3742 return cubemaptexture;
3745 rtexture_t *R_GetCubemap(const char *basename)
3748 for (i = 0;i < r_texture_numcubemaps;i++)
3749 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
3750 return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
3751 if (i >= MAX_CUBEMAPS)
3752 return r_texture_whitecube;
3753 r_texture_numcubemaps++;
3754 strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
3755 r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
3756 return r_texture_cubemaps[i].texture;
3759 void R_FreeCubemaps(void)
3762 for (i = 0;i < r_texture_numcubemaps;i++)
3764 if (developer_loading.integer)
3765 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
3766 if (r_texture_cubemaps[i].texture)
3767 R_FreeTexture(r_texture_cubemaps[i].texture);
3769 r_texture_numcubemaps = 0;
3772 void R_Main_FreeViewCache(void)
3774 if (r_refdef.viewcache.entityvisible)
3775 Mem_Free(r_refdef.viewcache.entityvisible);
3776 if (r_refdef.viewcache.world_pvsbits)
3777 Mem_Free(r_refdef.viewcache.world_pvsbits);
3778 if (r_refdef.viewcache.world_leafvisible)
3779 Mem_Free(r_refdef.viewcache.world_leafvisible);
3780 if (r_refdef.viewcache.world_surfacevisible)
3781 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3782 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3785 void R_Main_ResizeViewCache(void)
3787 int numentities = r_refdef.scene.numentities;
3788 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3789 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3790 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3791 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3792 if (r_refdef.viewcache.maxentities < numentities)
3794 r_refdef.viewcache.maxentities = numentities;
3795 if (r_refdef.viewcache.entityvisible)
3796 Mem_Free(r_refdef.viewcache.entityvisible);
3797 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3799 if (r_refdef.viewcache.world_numclusters != numclusters)
3801 r_refdef.viewcache.world_numclusters = numclusters;
3802 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3803 if (r_refdef.viewcache.world_pvsbits)
3804 Mem_Free(r_refdef.viewcache.world_pvsbits);
3805 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3807 if (r_refdef.viewcache.world_numleafs != numleafs)
3809 r_refdef.viewcache.world_numleafs = numleafs;
3810 if (r_refdef.viewcache.world_leafvisible)
3811 Mem_Free(r_refdef.viewcache.world_leafvisible);
3812 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3814 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3816 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3817 if (r_refdef.viewcache.world_surfacevisible)
3818 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3819 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3823 extern rtexture_t *loadingscreentexture;
3824 void gl_main_start(void)
3826 loadingscreentexture = NULL;
3827 r_texture_blanknormalmap = NULL;
3828 r_texture_white = NULL;
3829 r_texture_grey128 = NULL;
3830 r_texture_black = NULL;
3831 r_texture_whitecube = NULL;
3832 r_texture_normalizationcube = NULL;
3833 r_texture_fogattenuation = NULL;
3834 r_texture_fogheighttexture = NULL;
3835 r_texture_gammaramps = NULL;
3836 r_texture_numcubemaps = 0;
3838 r_loaddds = r_texture_dds_load.integer != 0;
3839 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3841 switch(vid.renderpath)
3843 case RENDERPATH_GL20:
3844 case RENDERPATH_D3D9:
3845 case RENDERPATH_D3D10:
3846 case RENDERPATH_D3D11:
3847 case RENDERPATH_SOFT:
3848 case RENDERPATH_GLES2:
3849 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3850 Cvar_SetValueQuick(&gl_combine, 1);
3851 Cvar_SetValueQuick(&r_glsl, 1);
3852 r_loadnormalmap = true;
3856 case RENDERPATH_GL13:
3857 case RENDERPATH_GLES1:
3858 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3859 Cvar_SetValueQuick(&gl_combine, 1);
3860 Cvar_SetValueQuick(&r_glsl, 0);
3861 r_loadnormalmap = false;
3862 r_loadgloss = false;
3865 case RENDERPATH_GL11:
3866 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3867 Cvar_SetValueQuick(&gl_combine, 0);
3868 Cvar_SetValueQuick(&r_glsl, 0);
3869 r_loadnormalmap = false;
3870 r_loadgloss = false;
3876 R_FrameData_Reset();
3880 memset(r_queries, 0, sizeof(r_queries));
3882 r_qwskincache = NULL;
3883 r_qwskincache_size = 0;
3885 // due to caching of texture_t references, the collision cache must be reset
3886 Collision_Cache_Reset(true);
3888 // set up r_skinframe loading system for textures
3889 memset(&r_skinframe, 0, sizeof(r_skinframe));
3890 r_skinframe.loadsequence = 1;
3891 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3893 r_main_texturepool = R_AllocTexturePool();
3894 R_BuildBlankTextures();
3896 if (vid.support.arb_texture_cube_map)
3899 R_BuildNormalizationCube();
3901 r_texture_fogattenuation = NULL;
3902 r_texture_fogheighttexture = NULL;
3903 r_texture_gammaramps = NULL;
3904 //r_texture_fogintensity = NULL;
3905 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3906 memset(&r_waterstate, 0, sizeof(r_waterstate));
3907 r_glsl_permutation = NULL;
3908 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3909 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3910 glslshaderstring = NULL;
3912 r_hlsl_permutation = NULL;
3913 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3914 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
3916 hlslshaderstring = NULL;
3917 memset(&r_svbsp, 0, sizeof (r_svbsp));
3919 r_refdef.fogmasktable_density = 0;
3922 void gl_main_shutdown(void)
3925 R_FrameData_Reset();
3927 R_Main_FreeViewCache();
3929 switch(vid.renderpath)
3931 case RENDERPATH_GL11:
3932 case RENDERPATH_GL13:
3933 case RENDERPATH_GL20:
3934 case RENDERPATH_GLES1:
3935 case RENDERPATH_GLES2:
3937 qglDeleteQueriesARB(r_maxqueries, r_queries);
3939 case RENDERPATH_D3D9:
3940 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3942 case RENDERPATH_D3D10:
3943 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3945 case RENDERPATH_D3D11:
3946 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3948 case RENDERPATH_SOFT:
3954 memset(r_queries, 0, sizeof(r_queries));
3956 r_qwskincache = NULL;
3957 r_qwskincache_size = 0;
3959 // clear out the r_skinframe state
3960 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3961 memset(&r_skinframe, 0, sizeof(r_skinframe));
3964 Mem_Free(r_svbsp.nodes);
3965 memset(&r_svbsp, 0, sizeof (r_svbsp));
3966 R_FreeTexturePool(&r_main_texturepool);
3967 loadingscreentexture = NULL;
3968 r_texture_blanknormalmap = NULL;
3969 r_texture_white = NULL;
3970 r_texture_grey128 = NULL;
3971 r_texture_black = NULL;
3972 r_texture_whitecube = NULL;
3973 r_texture_normalizationcube = NULL;
3974 r_texture_fogattenuation = NULL;
3975 r_texture_fogheighttexture = NULL;
3976 r_texture_gammaramps = NULL;
3977 r_texture_numcubemaps = 0;
3978 //r_texture_fogintensity = NULL;
3979 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3980 memset(&r_waterstate, 0, sizeof(r_waterstate));
3983 r_glsl_permutation = NULL;
3984 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3985 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
3986 glslshaderstring = NULL;
3988 r_hlsl_permutation = NULL;
3989 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3990 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
3992 hlslshaderstring = NULL;
3995 extern void CL_ParseEntityLump(char *entitystring);
3996 void gl_main_newmap(void)
3998 // FIXME: move this code to client
3999 char *entities, entname[MAX_QPATH];
4001 Mem_Free(r_qwskincache);
4002 r_qwskincache = NULL;
4003 r_qwskincache_size = 0;
4006 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4007 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4009 CL_ParseEntityLump(entities);
4013 if (cl.worldmodel->brush.entities)
4014 CL_ParseEntityLump(cl.worldmodel->brush.entities);
4016 R_Main_FreeViewCache();
4018 R_FrameData_Reset();
4021 void GL_Main_Init(void)
4023 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4025 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4026 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4027 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4028 if (gamemode == GAME_NEHAHRA)
4030 Cvar_RegisterVariable (&gl_fogenable);
4031 Cvar_RegisterVariable (&gl_fogdensity);
4032 Cvar_RegisterVariable (&gl_fogred);
4033 Cvar_RegisterVariable (&gl_foggreen);
4034 Cvar_RegisterVariable (&gl_fogblue);
4035 Cvar_RegisterVariable (&gl_fogstart);
4036 Cvar_RegisterVariable (&gl_fogend);
4037 Cvar_RegisterVariable (&gl_skyclip);
4039 Cvar_RegisterVariable(&r_motionblur);
4040 Cvar_RegisterVariable(&r_motionblur_maxblur);
4041 Cvar_RegisterVariable(&r_motionblur_bmin);
4042 Cvar_RegisterVariable(&r_motionblur_vmin);
4043 Cvar_RegisterVariable(&r_motionblur_vmax);
4044 Cvar_RegisterVariable(&r_motionblur_vcoeff);
4045 Cvar_RegisterVariable(&r_motionblur_randomize);
4046 Cvar_RegisterVariable(&r_damageblur);
4047 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4048 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4049 Cvar_RegisterVariable(&r_equalize_entities_by);
4050 Cvar_RegisterVariable(&r_equalize_entities_to);
4051 Cvar_RegisterVariable(&r_depthfirst);
4052 Cvar_RegisterVariable(&r_useinfinitefarclip);
4053 Cvar_RegisterVariable(&r_farclip_base);
4054 Cvar_RegisterVariable(&r_farclip_world);
4055 Cvar_RegisterVariable(&r_nearclip);
4056 Cvar_RegisterVariable(&r_deformvertexes);
4057 Cvar_RegisterVariable(&r_transparent);
4058 Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4059 Cvar_RegisterVariable(&r_showoverdraw);
4060 Cvar_RegisterVariable(&r_showbboxes);
4061 Cvar_RegisterVariable(&r_showsurfaces);
4062 Cvar_RegisterVariable(&r_showtris);
4063 Cvar_RegisterVariable(&r_shownormals);
4064 Cvar_RegisterVariable(&r_showlighting);
4065 Cvar_RegisterVariable(&r_showshadowvolumes);
4066 Cvar_RegisterVariable(&r_showcollisionbrushes);
4067 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4068 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4069 Cvar_RegisterVariable(&r_showdisabledepthtest);
4070 Cvar_RegisterVariable(&r_drawportals);
4071 Cvar_RegisterVariable(&r_drawentities);
4072 Cvar_RegisterVariable(&r_draw2d);
4073 Cvar_RegisterVariable(&r_drawworld);
4074 Cvar_RegisterVariable(&r_cullentities_trace);
4075 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4076 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4077 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4078 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4079 Cvar_RegisterVariable(&r_drawviewmodel);
4080 Cvar_RegisterVariable(&r_drawexteriormodel);
4081 Cvar_RegisterVariable(&r_speeds);
4082 Cvar_RegisterVariable(&r_fullbrights);
4083 Cvar_RegisterVariable(&r_wateralpha);
4084 Cvar_RegisterVariable(&r_dynamic);
4085 Cvar_RegisterVariable(&r_fakelight);
4086 Cvar_RegisterVariable(&r_fakelight_intensity);
4087 Cvar_RegisterVariable(&r_fullbright);
4088 Cvar_RegisterVariable(&r_shadows);
4089 Cvar_RegisterVariable(&r_shadows_darken);
4090 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4091 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4092 Cvar_RegisterVariable(&r_shadows_throwdistance);
4093 Cvar_RegisterVariable(&r_shadows_throwdirection);
4094 Cvar_RegisterVariable(&r_shadows_focus);
4095 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4096 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4097 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4098 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4099 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4100 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4101 Cvar_RegisterVariable(&r_fog_exp2);
4102 Cvar_RegisterVariable(&r_fog_clear);
4103 Cvar_RegisterVariable(&r_drawfog);
4104 Cvar_RegisterVariable(&r_transparentdepthmasking);
4105 Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4106 Cvar_RegisterVariable(&r_transparent_sortarraysize);
4107 Cvar_RegisterVariable(&r_texture_dds_load);
4108 Cvar_RegisterVariable(&r_texture_dds_save);
4109 Cvar_RegisterVariable(&r_textureunits);
4110 Cvar_RegisterVariable(&gl_combine);
4111 Cvar_RegisterVariable(&r_viewfbo);
4112 Cvar_RegisterVariable(&r_viewscale);
4113 Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4114 Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4115 Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4116 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4117 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4118 Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4119 Cvar_RegisterVariable(&r_glsl);
4120 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4121 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4122 Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4123 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4124 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4125 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4126 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4127 Cvar_RegisterVariable(&r_glsl_postprocess);
4128 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4129 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4130 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4131 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4132 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4133 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4134 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4135 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4137 Cvar_RegisterVariable(&r_water);
4138 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4139 Cvar_RegisterVariable(&r_water_clippingplanebias);
4140 Cvar_RegisterVariable(&r_water_refractdistort);
4141 Cvar_RegisterVariable(&r_water_reflectdistort);
4142 Cvar_RegisterVariable(&r_water_scissormode);
4143 Cvar_RegisterVariable(&r_lerpsprites);
4144 Cvar_RegisterVariable(&r_lerpmodels);
4145 Cvar_RegisterVariable(&r_lerplightstyles);
4146 Cvar_RegisterVariable(&r_waterscroll);
4147 Cvar_RegisterVariable(&r_bloom);
4148 Cvar_RegisterVariable(&r_bloom_colorscale);
4149 Cvar_RegisterVariable(&r_bloom_brighten);
4150 Cvar_RegisterVariable(&r_bloom_blur);
4151 Cvar_RegisterVariable(&r_bloom_resolution);
4152 Cvar_RegisterVariable(&r_bloom_colorexponent);
4153 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4154 Cvar_RegisterVariable(&r_hdr);
4155 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4156 Cvar_RegisterVariable(&r_hdr_glowintensity);
4157 Cvar_RegisterVariable(&r_hdr_range);
4158 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4159 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4160 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4161 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4162 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4163 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4164 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4165 Cvar_RegisterVariable(&developer_texturelogging);
4166 Cvar_RegisterVariable(&gl_lightmaps);
4167 Cvar_RegisterVariable(&r_test);
4168 Cvar_RegisterVariable(&r_glsl_saturation);
4169 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4170 Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4171 Cvar_RegisterVariable(&r_framedatasize);
4172 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4173 Cvar_SetValue("r_fullbrights", 0);
4174 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4176 Cvar_RegisterVariable(&r_track_sprites);
4177 Cvar_RegisterVariable(&r_track_sprites_flags);
4178 Cvar_RegisterVariable(&r_track_sprites_scalew);
4179 Cvar_RegisterVariable(&r_track_sprites_scaleh);
4180 Cvar_RegisterVariable(&r_overheadsprites_perspective);
4181 Cvar_RegisterVariable(&r_overheadsprites_pushback);
4182 Cvar_RegisterVariable(&r_overheadsprites_scalex);
4183 Cvar_RegisterVariable(&r_overheadsprites_scaley);
4186 extern void R_Textures_Init(void);
4187 extern void GL_Draw_Init(void);
4188 extern void GL_Main_Init(void);
4189 extern void R_Shadow_Init(void);
4190 extern void R_Sky_Init(void);
4191 extern void GL_Surf_Init(void);
4192 extern void R_Particles_Init(void);
4193 extern void R_Explosion_Init(void);
4194 extern void gl_backend_init(void);
4195 extern void Sbar_Init(void);
4196 extern void R_LightningBeams_Init(void);
4197 extern void Mod_RenderInit(void);
4198 extern void Font_Init(void);
4200 void Render_Init(void)
4213 R_LightningBeams_Init();
4222 extern char *ENGINE_EXTENSIONS;
4225 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4226 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4227 gl_version = (const char *)qglGetString(GL_VERSION);
4228 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4232 if (!gl_platformextensions)
4233 gl_platformextensions = "";
4235 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4236 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4237 Con_Printf("GL_VERSION: %s\n", gl_version);
4238 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4239 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4241 VID_CheckExtensions();
4243 // LordHavoc: report supported extensions
4244 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4246 // clear to black (loading plaque will be seen over this)
4247 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4250 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4254 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4256 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4259 p = r_refdef.view.frustum + i;
4264 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4268 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4272 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4276 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4280 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4284 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4288 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4292 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4300 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4304 for (i = 0;i < numplanes;i++)
4311 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4315 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4319 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4323 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4327 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4331 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4335 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4339 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4347 //==================================================================================
4349 // LordHavoc: this stores temporary data used within the same frame
4351 typedef struct r_framedata_mem_s
4353 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4354 size_t size; // how much usable space
4355 size_t current; // how much space in use
4356 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4357 size_t wantedsize; // how much space was allocated
4358 unsigned char *data; // start of real data (16byte aligned)
4362 static r_framedata_mem_t *r_framedata_mem;
4364 void R_FrameData_Reset(void)
4366 while (r_framedata_mem)
4368 r_framedata_mem_t *next = r_framedata_mem->purge;
4369 Mem_Free(r_framedata_mem);
4370 r_framedata_mem = next;
4374 void R_FrameData_Resize(void)
4377 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4378 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4379 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4381 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4382 newmem->wantedsize = wantedsize;
4383 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4384 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4385 newmem->current = 0;
4387 newmem->purge = r_framedata_mem;
4388 r_framedata_mem = newmem;
4392 void R_FrameData_NewFrame(void)
4394 R_FrameData_Resize();
4395 if (!r_framedata_mem)
4397 // if we ran out of space on the last frame, free the old memory now
4398 while (r_framedata_mem->purge)
4400 // repeatedly remove the second item in the list, leaving only head
4401 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4402 Mem_Free(r_framedata_mem->purge);
4403 r_framedata_mem->purge = next;
4405 // reset the current mem pointer
4406 r_framedata_mem->current = 0;
4407 r_framedata_mem->mark = 0;
4410 void *R_FrameData_Alloc(size_t size)
4414 // align to 16 byte boundary - the data pointer is already aligned, so we
4415 // only need to ensure the size of every allocation is also aligned
4416 size = (size + 15) & ~15;
4418 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4420 // emergency - we ran out of space, allocate more memory
4421 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4422 R_FrameData_Resize();
4425 data = r_framedata_mem->data + r_framedata_mem->current;
4426 r_framedata_mem->current += size;
4428 // count the usage for stats
4429 r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4430 r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4432 return (void *)data;
4435 void *R_FrameData_Store(size_t size, void *data)
4437 void *d = R_FrameData_Alloc(size);
4439 memcpy(d, data, size);
4443 void R_FrameData_SetMark(void)
4445 if (!r_framedata_mem)
4447 r_framedata_mem->mark = r_framedata_mem->current;
4450 void R_FrameData_ReturnToMark(void)
4452 if (!r_framedata_mem)
4454 r_framedata_mem->current = r_framedata_mem->mark;
4457 //==================================================================================
4459 // LordHavoc: animcache originally written by Echon, rewritten since then
4462 * Animation cache prevents re-generating mesh data for an animated model
4463 * multiple times in one frame for lighting, shadowing, reflections, etc.
4466 void R_AnimCache_Free(void)
4470 void R_AnimCache_ClearCache(void)
4473 entity_render_t *ent;
4475 for (i = 0;i < r_refdef.scene.numentities;i++)
4477 ent = r_refdef.scene.entities[i];
4478 ent->animcache_vertex3f = NULL;
4479 ent->animcache_normal3f = NULL;
4480 ent->animcache_svector3f = NULL;
4481 ent->animcache_tvector3f = NULL;
4482 ent->animcache_vertexmesh = NULL;
4483 ent->animcache_vertex3fbuffer = NULL;
4484 ent->animcache_vertexmeshbuffer = NULL;
4488 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4492 // check if we need the meshbuffers
4493 if (!vid.useinterleavedarrays)
4496 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4497 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4498 // TODO: upload vertex3f buffer?
4499 if (ent->animcache_vertexmesh)
4501 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4502 for (i = 0;i < numvertices;i++)
4503 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4504 if (ent->animcache_svector3f)
4505 for (i = 0;i < numvertices;i++)
4506 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4507 if (ent->animcache_tvector3f)
4508 for (i = 0;i < numvertices;i++)
4509 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4510 if (ent->animcache_normal3f)
4511 for (i = 0;i < numvertices;i++)
4512 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4513 // TODO: upload vertexmeshbuffer?
4517 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4519 dp_model_t *model = ent->model;
4521 // see if it's already cached this frame
4522 if (ent->animcache_vertex3f)
4524 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4525 if (wantnormals || wanttangents)
4527 if (ent->animcache_normal3f)
4528 wantnormals = false;
4529 if (ent->animcache_svector3f)
4530 wanttangents = false;
4531 if (wantnormals || wanttangents)
4533 numvertices = model->surfmesh.num_vertices;
4535 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4538 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4539 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4541 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4542 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4548 // see if this ent is worth caching
4549 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4551 // get some memory for this entity and generate mesh data
4552 numvertices = model->surfmesh.num_vertices;
4553 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4555 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4558 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4559 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4561 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4562 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4567 void R_AnimCache_CacheVisibleEntities(void)
4570 qboolean wantnormals = true;
4571 qboolean wanttangents = !r_showsurfaces.integer;
4573 switch(vid.renderpath)
4575 case RENDERPATH_GL20:
4576 case RENDERPATH_D3D9:
4577 case RENDERPATH_D3D10:
4578 case RENDERPATH_D3D11:
4579 case RENDERPATH_GLES2:
4581 case RENDERPATH_GL11:
4582 case RENDERPATH_GL13:
4583 case RENDERPATH_GLES1:
4584 wanttangents = false;
4586 case RENDERPATH_SOFT:
4590 if (r_shownormals.integer)
4591 wanttangents = wantnormals = true;
4593 // TODO: thread this
4594 // NOTE: R_PrepareRTLights() also caches entities
4596 for (i = 0;i < r_refdef.scene.numentities;i++)
4597 if (r_refdef.viewcache.entityvisible[i])
4598 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4601 //==================================================================================
4603 static void R_View_UpdateEntityLighting (void)
4606 entity_render_t *ent;
4607 vec3_t tempdiffusenormal, avg;
4608 vec_t f, fa, fd, fdd;
4609 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4611 for (i = 0;i < r_refdef.scene.numentities;i++)
4613 ent = r_refdef.scene.entities[i];
4615 // skip unseen models
4616 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4620 if (ent->model && ent->model->brush.num_leafs)
4622 // TODO: use modellight for r_ambient settings on world?
4623 VectorSet(ent->modellight_ambient, 0, 0, 0);
4624 VectorSet(ent->modellight_diffuse, 0, 0, 0);
4625 VectorSet(ent->modellight_lightdir, 0, 0, 1);
4629 // fetch the lighting from the worldmodel data
4630 VectorClear(ent->modellight_ambient);
4631 VectorClear(ent->modellight_diffuse);
4632 VectorClear(tempdiffusenormal);
4633 if (ent->flags & RENDER_LIGHT)
4636 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4638 // complete lightning for lit sprites
4639 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4640 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4642 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4643 org[2] = org[2] + r_overheadsprites_pushback.value;
4644 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4647 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4649 if(ent->flags & RENDER_EQUALIZE)
4651 // first fix up ambient lighting...
4652 if(r_equalize_entities_minambient.value > 0)
4654 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4657 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4658 if(fa < r_equalize_entities_minambient.value * fd)
4661 // fa'/fd' = minambient
4662 // fa'+0.25*fd' = fa+0.25*fd
4664 // fa' = fd' * minambient
4665 // fd'*(0.25+minambient) = fa+0.25*fd
4667 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4668 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4670 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4671 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
4672 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4673 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4678 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4680 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4681 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4685 // adjust brightness and saturation to target
4686 avg[0] = avg[1] = avg[2] = fa / f;
4687 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4688 avg[0] = avg[1] = avg[2] = fd / f;
4689 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4695 VectorSet(ent->modellight_ambient, 1, 1, 1);
4697 // move the light direction into modelspace coordinates for lighting code
4698 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4699 if(VectorLength2(ent->modellight_lightdir) == 0)
4700 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4701 VectorNormalize(ent->modellight_lightdir);
4705 #define MAX_LINEOFSIGHTTRACES 64
4707 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4710 vec3_t boxmins, boxmaxs;
4713 dp_model_t *model = r_refdef.scene.worldmodel;
4715 if (!model || !model->brush.TraceLineOfSight)
4718 // expand the box a little
4719 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4720 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4721 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4722 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4723 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4724 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4726 // return true if eye is inside enlarged box
4727 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4731 VectorCopy(eye, start);
4732 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4733 if (model->brush.TraceLineOfSight(model, start, end))
4736 // try various random positions
4737 for (i = 0;i < numsamples;i++)
4739 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4740 if (model->brush.TraceLineOfSight(model, start, end))
4748 static void R_View_UpdateEntityVisible (void)
4753 entity_render_t *ent;
4755 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4756 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4757 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
4758 : RENDER_EXTERIORMODEL;
4759 if (!r_drawviewmodel.integer)
4760 renderimask |= RENDER_VIEWMODEL;
4761 if (!r_drawexteriormodel.integer)
4762 renderimask |= RENDER_EXTERIORMODEL;
4763 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4765 // worldmodel can check visibility
4766 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4767 for (i = 0;i < r_refdef.scene.numentities;i++)
4769 ent = r_refdef.scene.entities[i];
4770 if (!(ent->flags & renderimask))
4771 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)))
4772 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))
4773 r_refdef.viewcache.entityvisible[i] = true;
4778 // no worldmodel or it can't check visibility
4779 for (i = 0;i < r_refdef.scene.numentities;i++)
4781 ent = r_refdef.scene.entities[i];
4782 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));
4785 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
4786 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4788 for (i = 0;i < r_refdef.scene.numentities;i++)
4790 if (!r_refdef.viewcache.entityvisible[i])
4792 ent = r_refdef.scene.entities[i];
4793 if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4795 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4797 continue; // temp entities do pvs only
4798 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4799 ent->last_trace_visibility = realtime;
4800 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4801 r_refdef.viewcache.entityvisible[i] = 0;
4807 /// only used if skyrendermasked, and normally returns false
4808 int R_DrawBrushModelsSky (void)
4811 entity_render_t *ent;
4814 for (i = 0;i < r_refdef.scene.numentities;i++)
4816 if (!r_refdef.viewcache.entityvisible[i])
4818 ent = r_refdef.scene.entities[i];
4819 if (!ent->model || !ent->model->DrawSky)
4821 ent->model->DrawSky(ent);
4827 static void R_DrawNoModel(entity_render_t *ent);
4828 static void R_DrawModels(void)
4831 entity_render_t *ent;
4833 for (i = 0;i < r_refdef.scene.numentities;i++)
4835 if (!r_refdef.viewcache.entityvisible[i])
4837 ent = r_refdef.scene.entities[i];
4838 r_refdef.stats.entities++;
4840 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
4843 Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
4844 Con_Printf("R_DrawModels\n");
4845 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]);
4846 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);
4847 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);
4850 if (ent->model && ent->model->Draw != NULL)
4851 ent->model->Draw(ent);
4857 static void R_DrawModelsDepth(void)
4860 entity_render_t *ent;
4862 for (i = 0;i < r_refdef.scene.numentities;i++)
4864 if (!r_refdef.viewcache.entityvisible[i])
4866 ent = r_refdef.scene.entities[i];
4867 if (ent->model && ent->model->DrawDepth != NULL)
4868 ent->model->DrawDepth(ent);
4872 static void R_DrawModelsDebug(void)
4875 entity_render_t *ent;
4877 for (i = 0;i < r_refdef.scene.numentities;i++)
4879 if (!r_refdef.viewcache.entityvisible[i])
4881 ent = r_refdef.scene.entities[i];
4882 if (ent->model && ent->model->DrawDebug != NULL)
4883 ent->model->DrawDebug(ent);
4887 static void R_DrawModelsAddWaterPlanes(void)
4890 entity_render_t *ent;
4892 for (i = 0;i < r_refdef.scene.numentities;i++)
4894 if (!r_refdef.viewcache.entityvisible[i])
4896 ent = r_refdef.scene.entities[i];
4897 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4898 ent->model->DrawAddWaterPlanes(ent);
4902 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4904 if (r_hdr_irisadaptation.integer)
4908 vec3_t diffusenormal;
4913 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4914 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
4915 brightness = max(0.0000001f, brightness);
4916 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4917 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4918 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
4919 current = r_hdr_irisadaptation_value.value;
4921 current = min(current + adjust, goal);
4922 else if (current > goal)
4923 current = max(current - adjust, goal);
4924 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4925 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4927 else if (r_hdr_irisadaptation_value.value != 1.0f)
4928 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4931 static void R_View_SetFrustum(const int *scissor)
4934 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
4935 vec3_t forward, left, up, origin, v;
4939 // flipped x coordinates (because x points left here)
4940 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4941 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4943 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
4944 switch(vid.renderpath)
4946 case RENDERPATH_D3D9:
4947 case RENDERPATH_D3D10:
4948 case RENDERPATH_D3D11:
4949 // non-flipped y coordinates
4950 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4951 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4953 case RENDERPATH_SOFT:
4954 case RENDERPATH_GL11:
4955 case RENDERPATH_GL13:
4956 case RENDERPATH_GL20:
4957 case RENDERPATH_GLES1:
4958 case RENDERPATH_GLES2:
4959 // non-flipped y coordinates
4960 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4961 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4966 // we can't trust r_refdef.view.forward and friends in reflected scenes
4967 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4970 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4971 r_refdef.view.frustum[0].normal[1] = 0 - 0;
4972 r_refdef.view.frustum[0].normal[2] = -1 - 0;
4973 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4974 r_refdef.view.frustum[1].normal[1] = 0 + 0;
4975 r_refdef.view.frustum[1].normal[2] = -1 + 0;
4976 r_refdef.view.frustum[2].normal[0] = 0 - 0;
4977 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4978 r_refdef.view.frustum[2].normal[2] = -1 - 0;
4979 r_refdef.view.frustum[3].normal[0] = 0 + 0;
4980 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4981 r_refdef.view.frustum[3].normal[2] = -1 + 0;
4985 zNear = r_refdef.nearclip;
4986 nudge = 1.0 - 1.0 / (1<<23);
4987 r_refdef.view.frustum[4].normal[0] = 0 - 0;
4988 r_refdef.view.frustum[4].normal[1] = 0 - 0;
4989 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4990 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4991 r_refdef.view.frustum[5].normal[0] = 0 + 0;
4992 r_refdef.view.frustum[5].normal[1] = 0 + 0;
4993 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
4994 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5000 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5001 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5002 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5003 r_refdef.view.frustum[0].dist = m[15] - m[12];
5005 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5006 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5007 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5008 r_refdef.view.frustum[1].dist = m[15] + m[12];
5010 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5011 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5012 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5013 r_refdef.view.frustum[2].dist = m[15] - m[13];
5015 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5016 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5017 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5018 r_refdef.view.frustum[3].dist = m[15] + m[13];
5020 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5021 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5022 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5023 r_refdef.view.frustum[4].dist = m[15] - m[14];
5025 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5026 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5027 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5028 r_refdef.view.frustum[5].dist = m[15] + m[14];
5031 if (r_refdef.view.useperspective)
5033 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5034 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]);
5035 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]);
5036 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]);
5037 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]);
5039 // then the normals from the corners relative to origin
5040 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5041 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5042 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5043 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5045 // in a NORMAL view, forward cross left == up
5046 // in a REFLECTED view, forward cross left == down
5047 // so our cross products above need to be adjusted for a left handed coordinate system
5048 CrossProduct(forward, left, v);
5049 if(DotProduct(v, up) < 0)
5051 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5052 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5053 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5054 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5057 // Leaving those out was a mistake, those were in the old code, and they
5058 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5059 // I couldn't reproduce it after adding those normalizations. --blub
5060 VectorNormalize(r_refdef.view.frustum[0].normal);
5061 VectorNormalize(r_refdef.view.frustum[1].normal);
5062 VectorNormalize(r_refdef.view.frustum[2].normal);
5063 VectorNormalize(r_refdef.view.frustum[3].normal);
5065 // make the corners absolute
5066 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5067 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5068 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5069 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5072 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5074 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5075 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5076 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5077 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5078 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5082 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5083 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5084 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5085 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5086 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5087 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5088 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5089 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5090 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5091 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5093 r_refdef.view.numfrustumplanes = 5;
5095 if (r_refdef.view.useclipplane)
5097 r_refdef.view.numfrustumplanes = 6;
5098 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5101 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5102 PlaneClassify(r_refdef.view.frustum + i);
5104 // LordHavoc: note to all quake engine coders, Quake had a special case
5105 // for 90 degrees which assumed a square view (wrong), so I removed it,
5106 // Quake2 has it disabled as well.
5108 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5109 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5110 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5111 //PlaneClassify(&frustum[0]);
5113 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5114 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5115 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5116 //PlaneClassify(&frustum[1]);
5118 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5119 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5120 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5121 //PlaneClassify(&frustum[2]);
5123 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5124 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5125 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5126 //PlaneClassify(&frustum[3]);
5129 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5130 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5131 //PlaneClassify(&frustum[4]);
5134 void R_View_UpdateWithScissor(const int *myscissor)
5136 R_Main_ResizeViewCache();
5137 R_View_SetFrustum(myscissor);
5138 R_View_WorldVisibility(r_refdef.view.useclipplane);
5139 R_View_UpdateEntityVisible();
5140 R_View_UpdateEntityLighting();
5143 void R_View_Update(void)
5145 R_Main_ResizeViewCache();
5146 R_View_SetFrustum(NULL);
5147 R_View_WorldVisibility(r_refdef.view.useclipplane);
5148 R_View_UpdateEntityVisible();
5149 R_View_UpdateEntityLighting();
5152 float viewscalefpsadjusted = 1.0f;
5154 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5156 float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5157 scale = bound(0.03125f, scale, 1.0f);
5158 *outwidth = (int)ceil(width * scale);
5159 *outheight = (int)ceil(height * scale);
5162 void R_Mesh_SetMainRenderTargets(void)
5164 if (r_bloomstate.fbo_framebuffer)
5165 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5167 R_Mesh_ResetRenderTargets();
5170 void R_SetupView(qboolean allowwaterclippingplane)
5172 const float *customclipplane = NULL;
5174 int scaledwidth, scaledheight;
5175 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5177 // LordHavoc: couldn't figure out how to make this approach the
5178 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5179 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5180 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5181 dist = r_refdef.view.clipplane.dist;
5182 plane[0] = r_refdef.view.clipplane.normal[0];
5183 plane[1] = r_refdef.view.clipplane.normal[1];
5184 plane[2] = r_refdef.view.clipplane.normal[2];
5186 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5189 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5190 if (!r_refdef.view.useperspective)
5191 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);
5192 else if (vid.stencil && r_useinfinitefarclip.integer)
5193 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);
5195 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);
5196 R_Mesh_SetMainRenderTargets();
5197 R_SetViewport(&r_refdef.view.viewport);
5198 if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5200 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5201 float screenplane[4];
5202 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5203 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5204 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5205 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5206 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5210 void R_EntityMatrix(const matrix4x4_t *matrix)
5212 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5214 gl_modelmatrixchanged = false;
5215 gl_modelmatrix = *matrix;
5216 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5217 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5218 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5219 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5221 switch(vid.renderpath)
5223 case RENDERPATH_D3D9:
5225 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5226 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5229 case RENDERPATH_D3D10:
5230 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5232 case RENDERPATH_D3D11:
5233 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5235 case RENDERPATH_GL11:
5236 case RENDERPATH_GL13:
5237 case RENDERPATH_GLES1:
5238 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5240 case RENDERPATH_SOFT:
5241 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5242 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5244 case RENDERPATH_GL20:
5245 case RENDERPATH_GLES2:
5246 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5247 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5253 void R_ResetViewRendering2D(void)
5255 r_viewport_t viewport;
5258 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5259 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);
5260 R_Mesh_ResetRenderTargets();
5261 R_SetViewport(&viewport);
5262 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5263 GL_Color(1, 1, 1, 1);
5264 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5265 GL_BlendFunc(GL_ONE, GL_ZERO);
5266 GL_ScissorTest(false);
5267 GL_DepthMask(false);
5268 GL_DepthRange(0, 1);
5269 GL_DepthTest(false);
5270 GL_DepthFunc(GL_LEQUAL);
5271 R_EntityMatrix(&identitymatrix);
5272 R_Mesh_ResetTextureState();
5273 GL_PolygonOffset(0, 0);
5274 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5275 switch(vid.renderpath)
5277 case RENDERPATH_GL11:
5278 case RENDERPATH_GL13:
5279 case RENDERPATH_GL20:
5280 case RENDERPATH_GLES1:
5281 case RENDERPATH_GLES2:
5282 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5284 case RENDERPATH_D3D9:
5285 case RENDERPATH_D3D10:
5286 case RENDERPATH_D3D11:
5287 case RENDERPATH_SOFT:
5290 GL_CullFace(GL_NONE);
5293 void R_ResetViewRendering3D(void)
5298 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5299 GL_Color(1, 1, 1, 1);
5300 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5301 GL_BlendFunc(GL_ONE, GL_ZERO);
5302 GL_ScissorTest(true);
5304 GL_DepthRange(0, 1);
5306 GL_DepthFunc(GL_LEQUAL);
5307 R_EntityMatrix(&identitymatrix);
5308 R_Mesh_ResetTextureState();
5309 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5310 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5311 switch(vid.renderpath)
5313 case RENDERPATH_GL11:
5314 case RENDERPATH_GL13:
5315 case RENDERPATH_GL20:
5316 case RENDERPATH_GLES1:
5317 case RENDERPATH_GLES2:
5318 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5320 case RENDERPATH_D3D9:
5321 case RENDERPATH_D3D10:
5322 case RENDERPATH_D3D11:
5323 case RENDERPATH_SOFT:
5326 GL_CullFace(r_refdef.view.cullface_back);
5331 R_RenderView_UpdateViewVectors
5334 static void R_RenderView_UpdateViewVectors(void)
5336 // break apart the view matrix into vectors for various purposes
5337 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5338 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5339 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5340 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5341 // make an inverted copy of the view matrix for tracking sprites
5342 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5345 void R_RenderScene(void);
5346 void R_RenderWaterPlanes(void);
5348 static void R_Water_StartFrame(void)
5351 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5352 r_waterstate_waterplane_t *p;
5354 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5357 switch(vid.renderpath)
5359 case RENDERPATH_GL20:
5360 case RENDERPATH_D3D9:
5361 case RENDERPATH_D3D10:
5362 case RENDERPATH_D3D11:
5363 case RENDERPATH_SOFT:
5364 case RENDERPATH_GLES2:
5366 case RENDERPATH_GL11:
5367 case RENDERPATH_GL13:
5368 case RENDERPATH_GLES1:
5372 // set waterwidth and waterheight to the water resolution that will be
5373 // used (often less than the screen resolution for faster rendering)
5374 R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5376 // calculate desired texture sizes
5377 // can't use water if the card does not support the texture size
5378 if (!r_water.integer || r_showsurfaces.integer)
5379 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5380 else if (vid.support.arb_texture_non_power_of_two)
5382 texturewidth = waterwidth;
5383 textureheight = waterheight;
5384 camerawidth = waterwidth;
5385 cameraheight = waterheight;
5389 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5390 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5391 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
5392 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
5395 // allocate textures as needed
5396 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5398 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5399 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5401 if (p->texture_refraction)
5402 R_FreeTexture(p->texture_refraction);
5403 p->texture_refraction = NULL;
5404 if (p->texture_reflection)
5405 R_FreeTexture(p->texture_reflection);
5406 p->texture_reflection = NULL;
5407 if (p->texture_camera)
5408 R_FreeTexture(p->texture_camera);
5409 p->texture_camera = NULL;
5411 memset(&r_waterstate, 0, sizeof(r_waterstate));
5412 r_waterstate.texturewidth = texturewidth;
5413 r_waterstate.textureheight = textureheight;
5414 r_waterstate.camerawidth = camerawidth;
5415 r_waterstate.cameraheight = cameraheight;
5418 if (r_waterstate.texturewidth)
5420 int scaledwidth, scaledheight;
5422 r_waterstate.enabled = true;
5424 // when doing a reduced render (HDR) we want to use a smaller area
5425 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5426 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5427 R_GetScaledViewSize(r_waterstate.waterwidth, r_waterstate.waterheight, &scaledwidth, &scaledheight);
5429 // set up variables that will be used in shader setup
5430 r_waterstate.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5431 r_waterstate.screenscale[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5432 r_waterstate.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5433 r_waterstate.screencenter[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5436 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5437 r_waterstate.numwaterplanes = 0;
5440 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5442 int triangleindex, planeindex;
5448 r_waterstate_waterplane_t *p;
5449 texture_t *t = R_GetCurrentTexture(surface->texture);
5451 // just use the first triangle with a valid normal for any decisions
5452 VectorClear(normal);
5453 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5455 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5456 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5457 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5458 TriangleNormal(vert[0], vert[1], vert[2], normal);
5459 if (VectorLength2(normal) >= 0.001)
5463 VectorCopy(normal, plane.normal);
5464 VectorNormalize(plane.normal);
5465 plane.dist = DotProduct(vert[0], plane.normal);
5466 PlaneClassify(&plane);
5467 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5469 // skip backfaces (except if nocullface is set)
5470 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5472 VectorNegate(plane.normal, plane.normal);
5474 PlaneClassify(&plane);
5478 // find a matching plane if there is one
5479 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5480 if(p->camera_entity == t->camera_entity)
5481 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5483 if (planeindex >= r_waterstate.maxwaterplanes)
5484 return; // nothing we can do, out of planes
5486 // if this triangle does not fit any known plane rendered this frame, add one
5487 if (planeindex >= r_waterstate.numwaterplanes)
5489 // store the new plane
5490 r_waterstate.numwaterplanes++;
5492 // clear materialflags and pvs
5493 p->materialflags = 0;
5494 p->pvsvalid = false;
5495 p->camera_entity = t->camera_entity;
5496 VectorCopy(surface->mins, p->mins);
5497 VectorCopy(surface->maxs, p->maxs);
5502 p->mins[0] = min(p->mins[0], surface->mins[0]);
5503 p->mins[1] = min(p->mins[1], surface->mins[1]);
5504 p->mins[2] = min(p->mins[2], surface->mins[2]);
5505 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5506 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5507 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5509 // merge this surface's materialflags into the waterplane
5510 p->materialflags |= t->currentmaterialflags;
5511 if(!(p->materialflags & MATERIALFLAG_CAMERA))
5513 // merge this surface's PVS into the waterplane
5514 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5515 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5516 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5518 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5524 static void R_Water_ProcessPlanes(void)
5527 r_refdef_view_t originalview;
5528 r_refdef_view_t myview;
5530 r_waterstate_waterplane_t *p;
5533 originalview = r_refdef.view;
5535 // make sure enough textures are allocated
5536 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5538 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5540 if (!p->texture_refraction)
5541 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);
5542 if (!p->texture_refraction)
5545 else if (p->materialflags & MATERIALFLAG_CAMERA)
5547 if (!p->texture_camera)
5548 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);
5549 if (!p->texture_camera)
5553 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5555 if (!p->texture_reflection)
5556 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);
5557 if (!p->texture_reflection)
5563 r_refdef.view = originalview;
5564 r_refdef.view.showdebug = false;
5565 r_refdef.view.width = r_waterstate.waterwidth;
5566 r_refdef.view.height = r_waterstate.waterheight;
5567 r_refdef.view.useclipplane = true;
5568 myview = r_refdef.view;
5569 r_waterstate.renderingscene = true;
5570 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5572 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5574 r_refdef.view = myview;
5575 if(r_water_scissormode.integer)
5578 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5579 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5582 // render reflected scene and copy into texture
5583 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5584 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5585 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5586 r_refdef.view.clipplane = p->plane;
5588 // reverse the cullface settings for this render
5589 r_refdef.view.cullface_front = GL_FRONT;
5590 r_refdef.view.cullface_back = GL_BACK;
5591 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5593 r_refdef.view.usecustompvs = true;
5595 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5597 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5600 R_ResetViewRendering3D();
5601 R_ClearScreen(r_refdef.fogenabled);
5602 if(r_water_scissormode.integer & 2)
5603 R_View_UpdateWithScissor(myscissor);
5606 if(r_water_scissormode.integer & 1)
5607 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5610 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);
5613 // render the normal view scene and copy into texture
5614 // (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)
5615 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5617 r_refdef.view = myview;
5618 if(r_water_scissormode.integer)
5621 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5622 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5625 r_waterstate.renderingrefraction = true;
5627 r_refdef.view.clipplane = p->plane;
5628 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5629 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5631 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5633 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5634 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5635 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5636 R_RenderView_UpdateViewVectors();
5637 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5639 r_refdef.view.usecustompvs = true;
5640 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);
5644 PlaneClassify(&r_refdef.view.clipplane);
5646 R_ResetViewRendering3D();
5647 R_ClearScreen(r_refdef.fogenabled);
5648 if(r_water_scissormode.integer & 2)
5649 R_View_UpdateWithScissor(myscissor);
5652 if(r_water_scissormode.integer & 1)
5653 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5656 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);
5657 r_waterstate.renderingrefraction = false;
5659 else if (p->materialflags & MATERIALFLAG_CAMERA)
5661 r_refdef.view = myview;
5663 r_refdef.view.clipplane = p->plane;
5664 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5665 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5667 r_refdef.view.width = r_waterstate.camerawidth;
5668 r_refdef.view.height = r_waterstate.cameraheight;
5669 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5670 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5672 if(p->camera_entity)
5674 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5675 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5678 // note: all of the view is used for displaying... so
5679 // there is no use in scissoring
5681 // reverse the cullface settings for this render
5682 r_refdef.view.cullface_front = GL_FRONT;
5683 r_refdef.view.cullface_back = GL_BACK;
5684 // also reverse the view matrix
5685 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
5686 R_RenderView_UpdateViewVectors();
5687 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5689 r_refdef.view.usecustompvs = true;
5690 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);
5693 // camera needs no clipplane
5694 r_refdef.view.useclipplane = false;
5696 PlaneClassify(&r_refdef.view.clipplane);
5698 R_ResetViewRendering3D();
5699 R_ClearScreen(r_refdef.fogenabled);
5703 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);
5704 r_waterstate.renderingrefraction = false;
5708 if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5709 r_waterstate.renderingscene = false;
5710 r_refdef.view = originalview;
5711 R_ResetViewRendering3D();
5712 R_ClearScreen(r_refdef.fogenabled);
5716 r_refdef.view = originalview;
5717 r_waterstate.renderingscene = false;
5718 Cvar_SetValueQuick(&r_water, 0);
5719 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
5723 void R_Bloom_StartFrame(void)
5725 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5726 int viewwidth, viewheight;
5729 if (r_viewscale_fpsscaling.integer)
5731 double actualframetime;
5732 double targetframetime;
5734 actualframetime = r_refdef.lastdrawscreentime;
5735 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5736 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5737 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5738 if (r_viewscale_fpsscaling_stepsize.value > 0)
5739 adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5740 viewscalefpsadjusted += adjust;
5741 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5744 viewscalefpsadjusted = 1.0f;
5746 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5748 switch(vid.renderpath)
5750 case RENDERPATH_GL20:
5751 case RENDERPATH_D3D9:
5752 case RENDERPATH_D3D10:
5753 case RENDERPATH_D3D11:
5754 case RENDERPATH_SOFT:
5755 case RENDERPATH_GLES2:
5757 case RENDERPATH_GL11:
5758 case RENDERPATH_GL13:
5759 case RENDERPATH_GLES1:
5763 // set bloomwidth and bloomheight to the bloom resolution that will be
5764 // used (often less than the screen resolution for faster rendering)
5765 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5766 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5767 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5768 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5769 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5771 // calculate desired texture sizes
5772 if (vid.support.arb_texture_non_power_of_two)
5774 screentexturewidth = vid.width;
5775 screentextureheight = vid.height;
5776 bloomtexturewidth = r_bloomstate.bloomwidth;
5777 bloomtextureheight = r_bloomstate.bloomheight;
5781 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
5782 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
5783 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
5784 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
5787 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))
5789 Cvar_SetValueQuick(&r_hdr, 0);
5790 Cvar_SetValueQuick(&r_bloom, 0);
5791 Cvar_SetValueQuick(&r_motionblur, 0);
5792 Cvar_SetValueQuick(&r_damageblur, 0);
5795 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)
5796 screentexturewidth = screentextureheight = 0;
5797 if (!r_hdr.integer && !r_bloom.integer)
5798 bloomtexturewidth = bloomtextureheight = 0;
5800 textype = TEXTYPE_COLORBUFFER;
5801 switch (vid.renderpath)
5803 case RENDERPATH_GL20:
5804 case RENDERPATH_GLES2:
5805 if (vid.support.ext_framebuffer_object)
5807 if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5808 if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5811 case RENDERPATH_GL11:
5812 case RENDERPATH_GL13:
5813 case RENDERPATH_GLES1:
5814 case RENDERPATH_D3D9:
5815 case RENDERPATH_D3D10:
5816 case RENDERPATH_D3D11:
5817 case RENDERPATH_SOFT:
5821 // allocate textures as needed
5822 if (r_bloomstate.screentexturewidth != screentexturewidth
5823 || r_bloomstate.screentextureheight != screentextureheight
5824 || r_bloomstate.bloomtexturewidth != bloomtexturewidth
5825 || r_bloomstate.bloomtextureheight != bloomtextureheight
5826 || r_bloomstate.texturetype != textype
5827 || r_bloomstate.viewfbo != r_viewfbo.integer)
5829 if (r_bloomstate.texture_bloom)
5830 R_FreeTexture(r_bloomstate.texture_bloom);
5831 r_bloomstate.texture_bloom = NULL;
5832 if (r_bloomstate.texture_screen)
5833 R_FreeTexture(r_bloomstate.texture_screen);
5834 r_bloomstate.texture_screen = NULL;
5835 if (r_bloomstate.fbo_framebuffer)
5836 R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
5837 r_bloomstate.fbo_framebuffer = 0;
5838 if (r_bloomstate.texture_framebuffercolor)
5839 R_FreeTexture(r_bloomstate.texture_framebuffercolor);
5840 r_bloomstate.texture_framebuffercolor = NULL;
5841 if (r_bloomstate.texture_framebufferdepth)
5842 R_FreeTexture(r_bloomstate.texture_framebufferdepth);
5843 r_bloomstate.texture_framebufferdepth = NULL;
5844 r_bloomstate.screentexturewidth = screentexturewidth;
5845 r_bloomstate.screentextureheight = screentextureheight;
5846 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5847 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);
5848 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
5850 // FIXME: choose depth bits based on a cvar
5851 r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
5852 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);
5853 r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5854 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5855 // render depth into one texture and normalmap into the other
5859 qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5860 qglReadBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5861 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
5862 if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
5863 Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
5866 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5867 r_bloomstate.bloomtextureheight = bloomtextureheight;
5868 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5869 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);
5870 r_bloomstate.viewfbo = r_viewfbo.integer;
5871 r_bloomstate.texturetype = textype;
5874 // when doing a reduced render (HDR) we want to use a smaller area
5875 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5876 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5877 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5878 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5879 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5881 // set up a texcoord array for the full resolution screen image
5882 // (we have to keep this around to copy back during final render)
5883 r_bloomstate.screentexcoord2f[0] = 0;
5884 r_bloomstate.screentexcoord2f[1] = (float)viewheight / (float)r_bloomstate.screentextureheight;
5885 r_bloomstate.screentexcoord2f[2] = (float)viewwidth / (float)r_bloomstate.screentexturewidth;
5886 r_bloomstate.screentexcoord2f[3] = (float)viewheight / (float)r_bloomstate.screentextureheight;
5887 r_bloomstate.screentexcoord2f[4] = (float)viewwidth / (float)r_bloomstate.screentexturewidth;
5888 r_bloomstate.screentexcoord2f[5] = 0;
5889 r_bloomstate.screentexcoord2f[6] = 0;
5890 r_bloomstate.screentexcoord2f[7] = 0;
5892 // set up a texcoord array for the reduced resolution bloom image
5893 // (which will be additive blended over the screen image)
5894 r_bloomstate.bloomtexcoord2f[0] = 0;
5895 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5896 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5897 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5898 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5899 r_bloomstate.bloomtexcoord2f[5] = 0;
5900 r_bloomstate.bloomtexcoord2f[6] = 0;
5901 r_bloomstate.bloomtexcoord2f[7] = 0;
5903 switch(vid.renderpath)
5905 case RENDERPATH_GL11:
5906 case RENDERPATH_GL13:
5907 case RENDERPATH_GL20:
5908 case RENDERPATH_SOFT:
5909 case RENDERPATH_GLES1:
5910 case RENDERPATH_GLES2:
5912 case RENDERPATH_D3D9:
5913 case RENDERPATH_D3D10:
5914 case RENDERPATH_D3D11:
5917 for (i = 0;i < 4;i++)
5919 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
5920 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
5921 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
5922 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
5928 if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth)
5930 r_bloomstate.enabled = true;
5931 r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer;
5934 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);
5936 if (r_bloomstate.fbo_framebuffer)
5937 r_refdef.view.clear = true;
5940 void R_Bloom_CopyBloomTexture(float colorscale)
5942 r_refdef.stats.bloom++;
5944 // scale down screen texture to the bloom texture size
5946 R_Mesh_SetMainRenderTargets();
5947 R_SetViewport(&r_bloomstate.viewport);
5948 GL_BlendFunc(GL_ONE, GL_ZERO);
5949 GL_Color(colorscale, colorscale, colorscale, 1);
5950 // 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...
5951 switch(vid.renderpath)
5953 case RENDERPATH_GL11:
5954 case RENDERPATH_GL13:
5955 case RENDERPATH_GL20:
5956 case RENDERPATH_GLES1:
5957 case RENDERPATH_GLES2:
5958 case RENDERPATH_SOFT:
5959 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5961 case RENDERPATH_D3D9:
5962 case RENDERPATH_D3D10:
5963 case RENDERPATH_D3D11:
5964 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5967 // TODO: do boxfilter scale-down in shader?
5968 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5969 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5970 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5972 // we now have a bloom image in the framebuffer
5973 // copy it into the bloom image texture for later processing
5974 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);
5975 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5978 void R_Bloom_CopyHDRTexture(void)
5980 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);
5981 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5984 void R_Bloom_MakeTexture(void)
5987 float xoffset, yoffset, r, brighten;
5989 r_refdef.stats.bloom++;
5991 R_ResetViewRendering2D();
5993 // we have a bloom image in the framebuffer
5995 R_SetViewport(&r_bloomstate.viewport);
5997 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6000 r = bound(0, r_bloom_colorexponent.value / x, 1);
6001 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6003 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
6004 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
6005 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6006 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6008 // copy the vertically blurred bloom view to a texture
6009 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);
6010 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6013 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
6014 brighten = r_bloom_brighten.value;
6015 if (r_bloomstate.hdr)
6016 brighten *= r_hdr_range.value;
6017 brighten = sqrt(brighten);
6019 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6020 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
6022 for (dir = 0;dir < 2;dir++)
6024 // blend on at multiple vertical offsets to achieve a vertical blur
6025 // TODO: do offset blends using GLSL
6026 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6027 GL_BlendFunc(GL_ONE, GL_ZERO);
6028 for (x = -range;x <= range;x++)
6030 if (!dir){xoffset = 0;yoffset = x;}
6031 else {xoffset = x;yoffset = 0;}
6032 xoffset /= (float)r_bloomstate.bloomtexturewidth;
6033 yoffset /= (float)r_bloomstate.bloomtextureheight;
6034 // compute a texcoord array with the specified x and y offset
6035 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
6036 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6037 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6038 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6039 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6040 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
6041 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
6042 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
6043 // this r value looks like a 'dot' particle, fading sharply to
6044 // black at the edges
6045 // (probably not realistic but looks good enough)
6046 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6047 //r = brighten/(range*2+1);
6048 r = brighten / (range * 2 + 1);
6050 r *= (1 - x*x/(float)(range*range));
6051 GL_Color(r, r, r, 1);
6052 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6053 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6054 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6055 GL_BlendFunc(GL_ONE, GL_ONE);
6058 // copy the vertically blurred bloom view to a texture
6059 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);
6060 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6064 void R_HDR_RenderBloomTexture(void)
6066 int oldwidth, oldheight;
6067 float oldcolorscale;
6068 qboolean oldwaterstate;
6070 oldwaterstate = r_waterstate.enabled;
6071 oldcolorscale = r_refdef.view.colorscale;
6072 oldwidth = r_refdef.view.width;
6073 oldheight = r_refdef.view.height;
6074 r_refdef.view.width = r_bloomstate.bloomwidth;
6075 r_refdef.view.height = r_bloomstate.bloomheight;
6077 if(r_hdr.integer < 2)
6078 r_waterstate.enabled = false;
6080 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
6081 // TODO: add exposure compensation features
6082 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6084 r_refdef.view.showdebug = false;
6085 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6087 R_ResetViewRendering3D();
6089 R_ClearScreen(r_refdef.fogenabled);
6090 if (r_timereport_active)
6091 R_TimeReport("HDRclear");
6094 if (r_timereport_active)
6095 R_TimeReport("visibility");
6097 // only do secondary renders with HDR if r_hdr is 2 or higher
6098 r_waterstate.numwaterplanes = 0;
6099 if (r_waterstate.enabled)
6100 R_RenderWaterPlanes();
6102 r_refdef.view.showdebug = true;
6104 r_waterstate.numwaterplanes = 0;
6106 R_ResetViewRendering2D();
6108 R_Bloom_CopyHDRTexture();
6109 R_Bloom_MakeTexture();
6111 // restore the view settings
6112 r_waterstate.enabled = oldwaterstate;
6113 r_refdef.view.width = oldwidth;
6114 r_refdef.view.height = oldheight;
6115 r_refdef.view.colorscale = oldcolorscale;
6117 R_ResetViewRendering3D();
6119 R_ClearScreen(r_refdef.fogenabled);
6120 if (r_timereport_active)
6121 R_TimeReport("viewclear");
6124 static void R_BlendView(void)
6126 unsigned int permutation;
6127 float uservecs[4][4];
6129 switch (vid.renderpath)
6131 case RENDERPATH_GL20:
6132 case RENDERPATH_D3D9:
6133 case RENDERPATH_D3D10:
6134 case RENDERPATH_D3D11:
6135 case RENDERPATH_SOFT:
6136 case RENDERPATH_GLES2:
6138 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6139 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6140 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6141 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6142 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6144 if (r_bloomstate.texture_screen)
6146 // make sure the buffer is available
6147 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6149 R_ResetViewRendering2D();
6150 R_Mesh_SetMainRenderTargets();
6152 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6154 // declare variables
6156 static float avgspeed;
6158 speed = VectorLength(cl.movement_velocity);
6160 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
6161 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
6163 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
6164 speed = bound(0, speed, 1);
6165 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
6167 // calculate values into a standard alpha
6168 cl.motionbluralpha = 1 - exp(-
6170 (r_motionblur.value * speed / 80)
6172 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6175 max(0.0001, cl.time - cl.oldtime) // fps independent
6178 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6179 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6181 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6183 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6184 GL_Color(1, 1, 1, cl.motionbluralpha);
6185 switch(vid.renderpath)
6187 case RENDERPATH_GL11:
6188 case RENDERPATH_GL13:
6189 case RENDERPATH_GL20:
6190 case RENDERPATH_GLES1:
6191 case RENDERPATH_GLES2:
6192 case RENDERPATH_SOFT:
6193 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6195 case RENDERPATH_D3D9:
6196 case RENDERPATH_D3D10:
6197 case RENDERPATH_D3D11:
6198 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6201 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6202 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6203 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6207 // copy view into the screen texture
6208 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);
6209 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6211 else if (!r_bloomstate.texture_bloom)
6213 // we may still have to do view tint...
6214 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6216 // apply a color tint to the whole view
6217 R_ResetViewRendering2D();
6218 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6219 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6220 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6221 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6222 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6224 break; // no screen processing, no bloom, skip it
6227 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6229 // render simple bloom effect
6230 // copy the screen and shrink it and darken it for the bloom process
6231 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6232 // make the bloom texture
6233 R_Bloom_MakeTexture();
6236 #if _MSC_VER >= 1400
6237 #define sscanf sscanf_s
6239 memset(uservecs, 0, sizeof(uservecs));
6240 if (r_glsl_postprocess_uservec1_enable.integer)
6241 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6242 if (r_glsl_postprocess_uservec2_enable.integer)
6243 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6244 if (r_glsl_postprocess_uservec3_enable.integer)
6245 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6246 if (r_glsl_postprocess_uservec4_enable.integer)
6247 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6249 R_ResetViewRendering2D();
6250 GL_Color(1, 1, 1, 1);
6251 GL_BlendFunc(GL_ONE, GL_ZERO);
6253 switch(vid.renderpath)
6255 case RENDERPATH_GL20:
6256 case RENDERPATH_GLES2:
6257 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6258 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6259 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_bloomstate.texture_screen);
6260 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_bloomstate.texture_bloom );
6261 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6262 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]);
6263 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6264 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]);
6265 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]);
6266 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]);
6267 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]);
6268 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6269 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6270 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);
6272 case RENDERPATH_D3D9:
6274 // 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...
6275 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6276 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6277 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6278 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6279 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6280 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6281 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6282 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6283 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6284 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6285 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6286 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6287 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6288 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6291 case RENDERPATH_D3D10:
6292 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6294 case RENDERPATH_D3D11:
6295 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6297 case RENDERPATH_SOFT:
6298 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6299 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6300 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6301 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6302 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6303 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6304 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6305 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6306 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6307 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6308 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6309 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6310 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6311 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6316 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6317 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6319 case RENDERPATH_GL11:
6320 case RENDERPATH_GL13:
6321 case RENDERPATH_GLES1:
6322 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6324 // apply a color tint to the whole view
6325 R_ResetViewRendering2D();
6326 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6327 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6328 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6329 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6330 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6336 matrix4x4_t r_waterscrollmatrix;
6338 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6340 if (r_refdef.fog_density)
6342 r_refdef.fogcolor[0] = r_refdef.fog_red;
6343 r_refdef.fogcolor[1] = r_refdef.fog_green;
6344 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6346 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6347 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6348 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6349 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6353 VectorCopy(r_refdef.fogcolor, fogvec);
6354 // color.rgb *= ContrastBoost * SceneBrightness;
6355 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6356 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6357 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6358 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6363 void R_UpdateVariables(void)
6367 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6369 r_refdef.farclip = r_farclip_base.value;
6370 if (r_refdef.scene.worldmodel)
6371 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6372 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6374 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6375 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6376 r_refdef.polygonfactor = 0;
6377 r_refdef.polygonoffset = 0;
6378 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6379 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6381 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6382 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6383 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6384 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6385 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6386 if (FAKELIGHT_ENABLED)
6388 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6390 if (r_showsurfaces.integer)
6392 r_refdef.scene.rtworld = false;
6393 r_refdef.scene.rtworldshadows = false;
6394 r_refdef.scene.rtdlight = false;
6395 r_refdef.scene.rtdlightshadows = false;
6396 r_refdef.lightmapintensity = 0;
6399 if (gamemode == GAME_NEHAHRA)
6401 if (gl_fogenable.integer)
6403 r_refdef.oldgl_fogenable = true;
6404 r_refdef.fog_density = gl_fogdensity.value;
6405 r_refdef.fog_red = gl_fogred.value;
6406 r_refdef.fog_green = gl_foggreen.value;
6407 r_refdef.fog_blue = gl_fogblue.value;
6408 r_refdef.fog_alpha = 1;
6409 r_refdef.fog_start = 0;
6410 r_refdef.fog_end = gl_skyclip.value;
6411 r_refdef.fog_height = 1<<30;
6412 r_refdef.fog_fadedepth = 128;
6414 else if (r_refdef.oldgl_fogenable)
6416 r_refdef.oldgl_fogenable = false;
6417 r_refdef.fog_density = 0;
6418 r_refdef.fog_red = 0;
6419 r_refdef.fog_green = 0;
6420 r_refdef.fog_blue = 0;
6421 r_refdef.fog_alpha = 0;
6422 r_refdef.fog_start = 0;
6423 r_refdef.fog_end = 0;
6424 r_refdef.fog_height = 1<<30;
6425 r_refdef.fog_fadedepth = 128;
6429 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6430 r_refdef.fog_start = max(0, r_refdef.fog_start);
6431 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6433 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6435 if (r_refdef.fog_density && r_drawfog.integer)
6437 r_refdef.fogenabled = true;
6438 // this is the point where the fog reaches 0.9986 alpha, which we
6439 // consider a good enough cutoff point for the texture
6440 // (0.9986 * 256 == 255.6)
6441 if (r_fog_exp2.integer)
6442 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6444 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6445 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6446 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6447 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6448 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6449 R_BuildFogHeightTexture();
6450 // fog color was already set
6451 // update the fog texture
6452 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)
6453 R_BuildFogTexture();
6454 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6455 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6458 r_refdef.fogenabled = false;
6460 switch(vid.renderpath)
6462 case RENDERPATH_GL20:
6463 case RENDERPATH_D3D9:
6464 case RENDERPATH_D3D10:
6465 case RENDERPATH_D3D11:
6466 case RENDERPATH_SOFT:
6467 case RENDERPATH_GLES2:
6468 if(v_glslgamma.integer && !vid_gammatables_trivial)
6470 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6472 // build GLSL gamma texture
6473 #define RAMPWIDTH 256
6474 unsigned short ramp[RAMPWIDTH * 3];
6475 unsigned char rampbgr[RAMPWIDTH][4];
6478 r_texture_gammaramps_serial = vid_gammatables_serial;
6480 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6481 for(i = 0; i < RAMPWIDTH; ++i)
6483 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6484 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6485 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6488 if (r_texture_gammaramps)
6490 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6494 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6500 // remove GLSL gamma texture
6503 case RENDERPATH_GL11:
6504 case RENDERPATH_GL13:
6505 case RENDERPATH_GLES1:
6510 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6511 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6517 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6518 if( scenetype != r_currentscenetype ) {
6519 // store the old scenetype
6520 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6521 r_currentscenetype = scenetype;
6522 // move in the new scene
6523 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6532 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6534 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6535 if( scenetype == r_currentscenetype ) {
6536 return &r_refdef.scene;
6538 return &r_scenes_store[ scenetype ];
6547 int dpsoftrast_test;
6548 void R_RenderView(void)
6550 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6552 dpsoftrast_test = r_test.integer;
6554 if (r_timereport_active)
6555 R_TimeReport("start");
6556 r_textureframe++; // used only by R_GetCurrentTexture
6557 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6559 if(R_CompileShader_CheckStaticParms())
6562 if (!r_drawentities.integer)
6563 r_refdef.scene.numentities = 0;
6565 R_AnimCache_ClearCache();
6566 R_FrameData_NewFrame();
6568 /* adjust for stereo display */
6569 if(R_Stereo_Active())
6571 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);
6572 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6575 if (r_refdef.view.isoverlay)
6577 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6578 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6579 R_TimeReport("depthclear");
6581 r_refdef.view.showdebug = false;
6583 r_waterstate.enabled = false;
6584 r_waterstate.numwaterplanes = 0;
6588 r_refdef.view.matrix = originalmatrix;
6594 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6596 r_refdef.view.matrix = originalmatrix;
6597 return; //Host_Error ("R_RenderView: NULL worldmodel");
6600 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6602 R_RenderView_UpdateViewVectors();
6604 R_Shadow_UpdateWorldLightSelection();
6606 R_Bloom_StartFrame();
6607 R_Water_StartFrame();
6610 if (r_timereport_active)
6611 R_TimeReport("viewsetup");
6613 R_ResetViewRendering3D();
6615 if (r_refdef.view.clear || r_refdef.fogenabled)
6617 R_ClearScreen(r_refdef.fogenabled);
6618 if (r_timereport_active)
6619 R_TimeReport("viewclear");
6621 r_refdef.view.clear = true;
6623 // this produces a bloom texture to be used in R_BlendView() later
6624 if (r_bloomstate.hdr)
6626 R_HDR_RenderBloomTexture();
6627 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6628 r_textureframe++; // used only by R_GetCurrentTexture
6631 r_refdef.view.showdebug = true;
6634 if (r_timereport_active)
6635 R_TimeReport("visibility");
6637 r_waterstate.numwaterplanes = 0;
6638 if (r_waterstate.enabled)
6639 R_RenderWaterPlanes();
6642 r_waterstate.numwaterplanes = 0;
6645 if (r_timereport_active)
6646 R_TimeReport("blendview");
6648 GL_Scissor(0, 0, vid.width, vid.height);
6649 GL_ScissorTest(false);
6651 r_refdef.view.matrix = originalmatrix;
6656 void R_RenderWaterPlanes(void)
6658 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6660 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6661 if (r_timereport_active)
6662 R_TimeReport("waterworld");
6665 // don't let sound skip if going slow
6666 if (r_refdef.scene.extraupdate)
6669 R_DrawModelsAddWaterPlanes();
6670 if (r_timereport_active)
6671 R_TimeReport("watermodels");
6673 if (r_waterstate.numwaterplanes)
6675 R_Water_ProcessPlanes();
6676 if (r_timereport_active)
6677 R_TimeReport("waterscenes");
6681 extern void R_DrawLightningBeams (void);
6682 extern void VM_CL_AddPolygonsToMeshQueue (void);
6683 extern void R_DrawPortals (void);
6684 extern cvar_t cl_locs_show;
6685 static void R_DrawLocs(void);
6686 static void R_DrawEntityBBoxes(void);
6687 static void R_DrawModelDecals(void);
6688 extern void R_DrawModelShadows(void);
6689 extern void R_DrawModelShadowMaps(void);
6690 extern cvar_t cl_decals_newsystem;
6691 extern qboolean r_shadow_usingdeferredprepass;
6692 void R_RenderScene(void)
6694 qboolean shadowmapping = false;
6696 if (r_timereport_active)
6697 R_TimeReport("beginscene");
6699 r_refdef.stats.renders++;
6703 // don't let sound skip if going slow
6704 if (r_refdef.scene.extraupdate)
6707 R_MeshQueue_BeginScene();
6711 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);
6713 if (r_timereport_active)
6714 R_TimeReport("skystartframe");
6716 if (cl.csqc_vidvars.drawworld)
6718 // don't let sound skip if going slow
6719 if (r_refdef.scene.extraupdate)
6722 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6724 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6725 if (r_timereport_active)
6726 R_TimeReport("worldsky");
6729 if (R_DrawBrushModelsSky() && r_timereport_active)
6730 R_TimeReport("bmodelsky");
6732 if (skyrendermasked && skyrenderlater)
6734 // we have to force off the water clipping plane while rendering sky
6738 if (r_timereport_active)
6739 R_TimeReport("sky");
6743 R_AnimCache_CacheVisibleEntities();
6744 if (r_timereport_active)
6745 R_TimeReport("animation");
6747 R_Shadow_PrepareLights();
6748 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6749 R_Shadow_PrepareModelShadows();
6750 if (r_timereport_active)
6751 R_TimeReport("preparelights");
6753 if (R_Shadow_ShadowMappingEnabled())
6754 shadowmapping = true;
6756 if (r_shadow_usingdeferredprepass)
6757 R_Shadow_DrawPrepass();
6759 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6761 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6762 if (r_timereport_active)
6763 R_TimeReport("worlddepth");
6765 if (r_depthfirst.integer >= 2)
6767 R_DrawModelsDepth();
6768 if (r_timereport_active)
6769 R_TimeReport("modeldepth");
6772 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6774 R_DrawModelShadowMaps();
6775 R_ResetViewRendering3D();
6776 // don't let sound skip if going slow
6777 if (r_refdef.scene.extraupdate)
6781 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6783 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6784 if (r_timereport_active)
6785 R_TimeReport("world");
6788 // don't let sound skip if going slow
6789 if (r_refdef.scene.extraupdate)
6793 if (r_timereport_active)
6794 R_TimeReport("models");
6796 // don't let sound skip if going slow
6797 if (r_refdef.scene.extraupdate)
6800 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6802 R_DrawModelShadows();
6803 R_ResetViewRendering3D();
6804 // don't let sound skip if going slow
6805 if (r_refdef.scene.extraupdate)
6809 if (!r_shadow_usingdeferredprepass)
6811 R_Shadow_DrawLights();
6812 if (r_timereport_active)
6813 R_TimeReport("rtlights");
6816 // don't let sound skip if going slow
6817 if (r_refdef.scene.extraupdate)
6820 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6822 R_DrawModelShadows();
6823 R_ResetViewRendering3D();
6824 // don't let sound skip if going slow
6825 if (r_refdef.scene.extraupdate)
6829 if (cl.csqc_vidvars.drawworld)
6831 if (cl_decals_newsystem.integer)
6833 R_DrawModelDecals();
6834 if (r_timereport_active)
6835 R_TimeReport("modeldecals");
6840 if (r_timereport_active)
6841 R_TimeReport("decals");
6845 if (r_timereport_active)
6846 R_TimeReport("particles");
6849 if (r_timereport_active)
6850 R_TimeReport("explosions");
6852 R_DrawLightningBeams();
6853 if (r_timereport_active)
6854 R_TimeReport("lightning");
6857 VM_CL_AddPolygonsToMeshQueue();
6859 if (r_refdef.view.showdebug)
6861 if (cl_locs_show.integer)
6864 if (r_timereport_active)
6865 R_TimeReport("showlocs");
6868 if (r_drawportals.integer)
6871 if (r_timereport_active)
6872 R_TimeReport("portals");
6875 if (r_showbboxes.value > 0)
6877 R_DrawEntityBBoxes();
6878 if (r_timereport_active)
6879 R_TimeReport("bboxes");
6883 if (r_transparent.integer)
6885 R_MeshQueue_RenderTransparent();
6886 if (r_timereport_active)
6887 R_TimeReport("drawtrans");
6890 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))
6892 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6893 if (r_timereport_active)
6894 R_TimeReport("worlddebug");
6895 R_DrawModelsDebug();
6896 if (r_timereport_active)
6897 R_TimeReport("modeldebug");
6900 if (cl.csqc_vidvars.drawworld)
6902 R_Shadow_DrawCoronas();
6903 if (r_timereport_active)
6904 R_TimeReport("coronas");
6909 GL_DepthTest(false);
6910 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6911 GL_Color(1, 1, 1, 1);
6912 qglBegin(GL_POLYGON);
6913 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6914 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6915 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6916 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
6918 qglBegin(GL_POLYGON);
6919 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]);
6920 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]);
6921 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]);
6922 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]);
6924 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
6928 // don't let sound skip if going slow
6929 if (r_refdef.scene.extraupdate)
6932 R_ResetViewRendering2D();
6935 static const unsigned short bboxelements[36] =
6945 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6948 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
6950 RSurf_ActiveWorldEntity();
6952 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6953 GL_DepthMask(false);
6954 GL_DepthRange(0, 1);
6955 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6956 // R_Mesh_ResetTextureState();
6958 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
6959 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
6960 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
6961 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
6962 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
6963 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
6964 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
6965 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
6966 R_FillColors(color4f, 8, cr, cg, cb, ca);
6967 if (r_refdef.fogenabled)
6969 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
6971 f1 = RSurf_FogVertex(v);
6973 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6974 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6975 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6978 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
6979 R_Mesh_ResetTextureState();
6980 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6981 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
6984 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6988 prvm_edict_t *edict;
6989 prvm_prog_t *prog_save = prog;
6991 // this function draws bounding boxes of server entities
6995 GL_CullFace(GL_NONE);
6996 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7000 for (i = 0;i < numsurfaces;i++)
7002 edict = PRVM_EDICT_NUM(surfacelist[i]);
7003 switch ((int)edict->fields.server->solid)
7005 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
7006 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
7007 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
7008 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7009 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
7010 default: Vector4Set(color, 0, 0, 0, 0.50);break;
7012 color[3] *= r_showbboxes.value;
7013 color[3] = bound(0, color[3], 1);
7014 GL_DepthTest(!r_showdisabledepthtest.integer);
7015 GL_CullFace(r_refdef.view.cullface_front);
7016 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7022 static void R_DrawEntityBBoxes(void)
7025 prvm_edict_t *edict;
7027 prvm_prog_t *prog_save = prog;
7029 // this function draws bounding boxes of server entities
7035 for (i = 0;i < prog->num_edicts;i++)
7037 edict = PRVM_EDICT_NUM(i);
7038 if (edict->priv.server->free)
7040 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7041 if(PRVM_EDICTFIELDEDICT(edict, prog->fieldoffsets.tag_entity) != 0)
7043 if(PRVM_EDICTFIELDEDICT(edict, prog->fieldoffsets.viewmodelforclient) != 0)
7045 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7046 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7052 static const int nomodelelement3i[24] =
7064 static const unsigned short nomodelelement3s[24] =
7076 static const float nomodelvertex3f[6*3] =
7086 static const float nomodelcolor4f[6*4] =
7088 0.0f, 0.0f, 0.5f, 1.0f,
7089 0.0f, 0.0f, 0.5f, 1.0f,
7090 0.0f, 0.5f, 0.0f, 1.0f,
7091 0.0f, 0.5f, 0.0f, 1.0f,
7092 0.5f, 0.0f, 0.0f, 1.0f,
7093 0.5f, 0.0f, 0.0f, 1.0f
7096 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7102 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);
7104 // this is only called once per entity so numsurfaces is always 1, and
7105 // surfacelist is always {0}, so this code does not handle batches
7107 if (rsurface.ent_flags & RENDER_ADDITIVE)
7109 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7110 GL_DepthMask(false);
7112 else if (rsurface.colormod[3] < 1)
7114 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7115 GL_DepthMask(false);
7119 GL_BlendFunc(GL_ONE, GL_ZERO);
7122 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7123 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7124 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7125 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7126 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7127 for (i = 0, c = color4f;i < 6;i++, c += 4)
7129 c[0] *= rsurface.colormod[0];
7130 c[1] *= rsurface.colormod[1];
7131 c[2] *= rsurface.colormod[2];
7132 c[3] *= rsurface.colormod[3];
7134 if (r_refdef.fogenabled)
7136 for (i = 0, c = color4f;i < 6;i++, c += 4)
7138 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7140 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7141 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7142 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7145 // R_Mesh_ResetTextureState();
7146 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7147 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7148 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7151 void R_DrawNoModel(entity_render_t *ent)
7154 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7155 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7156 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7158 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7161 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7163 vec3_t right1, right2, diff, normal;
7165 VectorSubtract (org2, org1, normal);
7167 // calculate 'right' vector for start
7168 VectorSubtract (r_refdef.view.origin, org1, diff);
7169 CrossProduct (normal, diff, right1);
7170 VectorNormalize (right1);
7172 // calculate 'right' vector for end
7173 VectorSubtract (r_refdef.view.origin, org2, diff);
7174 CrossProduct (normal, diff, right2);
7175 VectorNormalize (right2);
7177 vert[ 0] = org1[0] + width * right1[0];
7178 vert[ 1] = org1[1] + width * right1[1];
7179 vert[ 2] = org1[2] + width * right1[2];
7180 vert[ 3] = org1[0] - width * right1[0];
7181 vert[ 4] = org1[1] - width * right1[1];
7182 vert[ 5] = org1[2] - width * right1[2];
7183 vert[ 6] = org2[0] - width * right2[0];
7184 vert[ 7] = org2[1] - width * right2[1];
7185 vert[ 8] = org2[2] - width * right2[2];
7186 vert[ 9] = org2[0] + width * right2[0];
7187 vert[10] = org2[1] + width * right2[1];
7188 vert[11] = org2[2] + width * right2[2];
7191 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)
7193 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7194 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7195 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7196 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7197 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7198 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7199 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7200 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7201 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7202 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7203 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7204 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7207 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7212 VectorSet(v, x, y, z);
7213 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7214 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7216 if (i == mesh->numvertices)
7218 if (mesh->numvertices < mesh->maxvertices)
7220 VectorCopy(v, vertex3f);
7221 mesh->numvertices++;
7223 return mesh->numvertices;
7229 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7233 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7234 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7235 e = mesh->element3i + mesh->numtriangles * 3;
7236 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7238 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7239 if (mesh->numtriangles < mesh->maxtriangles)
7244 mesh->numtriangles++;
7246 element[1] = element[2];
7250 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7254 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7255 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7256 e = mesh->element3i + mesh->numtriangles * 3;
7257 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7259 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7260 if (mesh->numtriangles < mesh->maxtriangles)
7265 mesh->numtriangles++;
7267 element[1] = element[2];
7271 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7272 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7274 int planenum, planenum2;
7277 mplane_t *plane, *plane2;
7279 double temppoints[2][256*3];
7280 // figure out how large a bounding box we need to properly compute this brush
7282 for (w = 0;w < numplanes;w++)
7283 maxdist = max(maxdist, fabs(planes[w].dist));
7284 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7285 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7286 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7290 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7291 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7293 if (planenum2 == planenum)
7295 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);
7298 if (tempnumpoints < 3)
7300 // generate elements forming a triangle fan for this polygon
7301 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7305 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)
7307 texturelayer_t *layer;
7308 layer = t->currentlayers + t->currentnumlayers++;
7310 layer->depthmask = depthmask;
7311 layer->blendfunc1 = blendfunc1;
7312 layer->blendfunc2 = blendfunc2;
7313 layer->texture = texture;
7314 layer->texmatrix = *matrix;
7315 layer->color[0] = r;
7316 layer->color[1] = g;
7317 layer->color[2] = b;
7318 layer->color[3] = a;
7321 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7323 if(parms[0] == 0 && parms[1] == 0)
7325 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7326 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7331 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7334 index = parms[2] + r_refdef.scene.time * parms[3];
7335 index -= floor(index);
7336 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7339 case Q3WAVEFUNC_NONE:
7340 case Q3WAVEFUNC_NOISE:
7341 case Q3WAVEFUNC_COUNT:
7344 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7345 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7346 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7347 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7348 case Q3WAVEFUNC_TRIANGLE:
7350 f = index - floor(index);
7361 f = parms[0] + parms[1] * f;
7362 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7363 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7367 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7372 matrix4x4_t matrix, temp;
7373 switch(tcmod->tcmod)
7377 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7378 matrix = r_waterscrollmatrix;
7380 matrix = identitymatrix;
7382 case Q3TCMOD_ENTITYTRANSLATE:
7383 // this is used in Q3 to allow the gamecode to control texcoord
7384 // scrolling on the entity, which is not supported in darkplaces yet.
7385 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7387 case Q3TCMOD_ROTATE:
7388 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7389 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
7390 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7393 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7395 case Q3TCMOD_SCROLL:
7396 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
7398 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7399 w = (int) tcmod->parms[0];
7400 h = (int) tcmod->parms[1];
7401 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
7403 idx = (int) floor(f * w * h);
7404 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7406 case Q3TCMOD_STRETCH:
7407 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7408 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7410 case Q3TCMOD_TRANSFORM:
7411 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
7412 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
7413 VectorSet(tcmat + 6, 0 , 0 , 1);
7414 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
7415 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7417 case Q3TCMOD_TURBULENT:
7418 // this is handled in the RSurf_PrepareVertices function
7419 matrix = identitymatrix;
7423 Matrix4x4_Concat(texmatrix, &matrix, &temp);
7426 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7428 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7429 char name[MAX_QPATH];
7430 skinframe_t *skinframe;
7431 unsigned char pixels[296*194];
7432 strlcpy(cache->name, skinname, sizeof(cache->name));
7433 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7434 if (developer_loading.integer)
7435 Con_Printf("loading %s\n", name);
7436 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7437 if (!skinframe || !skinframe->base)
7440 fs_offset_t filesize;
7442 f = FS_LoadFile(name, tempmempool, true, &filesize);
7445 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7446 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7450 cache->skinframe = skinframe;
7453 texture_t *R_GetCurrentTexture(texture_t *t)
7456 const entity_render_t *ent = rsurface.entity;
7457 dp_model_t *model = ent->model;
7458 q3shaderinfo_layer_tcmod_t *tcmod;
7460 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7461 return t->currentframe;
7462 t->update_lastrenderframe = r_textureframe;
7463 t->update_lastrenderentity = (void *)ent;
7465 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7466 t->camera_entity = ent->entitynumber;
7468 t->camera_entity = 0;
7470 // switch to an alternate material if this is a q1bsp animated material
7472 texture_t *texture = t;
7473 int s = rsurface.ent_skinnum;
7474 if ((unsigned int)s >= (unsigned int)model->numskins)
7476 if (model->skinscenes)
7478 if (model->skinscenes[s].framecount > 1)
7479 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7481 s = model->skinscenes[s].firstframe;
7484 t = t + s * model->num_surfaces;
7487 // use an alternate animation if the entity's frame is not 0,
7488 // and only if the texture has an alternate animation
7489 if (rsurface.ent_alttextures && t->anim_total[1])
7490 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
7492 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
7494 texture->currentframe = t;
7497 // update currentskinframe to be a qw skin or animation frame
7498 if (rsurface.ent_qwskin >= 0)
7500 i = rsurface.ent_qwskin;
7501 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7503 r_qwskincache_size = cl.maxclients;
7505 Mem_Free(r_qwskincache);
7506 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7508 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7509 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7510 t->currentskinframe = r_qwskincache[i].skinframe;
7511 if (t->currentskinframe == NULL)
7512 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7514 else if (t->numskinframes >= 2)
7515 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7516 if (t->backgroundnumskinframes >= 2)
7517 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
7519 t->currentmaterialflags = t->basematerialflags;
7520 t->currentalpha = rsurface.colormod[3];
7521 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
7522 t->currentalpha *= r_wateralpha.value;
7523 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7524 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7525 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7526 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7527 if (!(rsurface.ent_flags & RENDER_LIGHT))
7528 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7529 else if (FAKELIGHT_ENABLED)
7531 // no modellight if using fakelight for the map
7533 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7535 // pick a model lighting mode
7536 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7537 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7539 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7541 if (rsurface.ent_flags & RENDER_ADDITIVE)
7542 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7543 else if (t->currentalpha < 1)
7544 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7545 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7546 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7547 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7548 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7549 if (t->backgroundnumskinframes)
7550 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7551 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7553 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7554 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7557 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7558 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7559 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7561 // there is no tcmod
7562 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7564 t->currenttexmatrix = r_waterscrollmatrix;
7565 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7567 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7569 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7570 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7573 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7574 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7575 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7576 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7578 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7579 if (t->currentskinframe->qpixels)
7580 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7581 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7582 if (!t->basetexture)
7583 t->basetexture = r_texture_notexture;
7584 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7585 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7586 t->nmaptexture = t->currentskinframe->nmap;
7587 if (!t->nmaptexture)
7588 t->nmaptexture = r_texture_blanknormalmap;
7589 t->glosstexture = r_texture_black;
7590 t->glowtexture = t->currentskinframe->glow;
7591 t->fogtexture = t->currentskinframe->fog;
7592 t->reflectmasktexture = t->currentskinframe->reflect;
7593 if (t->backgroundnumskinframes)
7595 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7596 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7597 t->backgroundglosstexture = r_texture_black;
7598 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7599 if (!t->backgroundnmaptexture)
7600 t->backgroundnmaptexture = r_texture_blanknormalmap;
7604 t->backgroundbasetexture = r_texture_white;
7605 t->backgroundnmaptexture = r_texture_blanknormalmap;
7606 t->backgroundglosstexture = r_texture_black;
7607 t->backgroundglowtexture = NULL;
7609 t->specularpower = r_shadow_glossexponent.value;
7610 // TODO: store reference values for these in the texture?
7611 t->specularscale = 0;
7612 if (r_shadow_gloss.integer > 0)
7614 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7616 if (r_shadow_glossintensity.value > 0)
7618 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7619 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7620 t->specularscale = r_shadow_glossintensity.value;
7623 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7625 t->glosstexture = r_texture_white;
7626 t->backgroundglosstexture = r_texture_white;
7627 t->specularscale = r_shadow_gloss2intensity.value;
7628 t->specularpower = r_shadow_gloss2exponent.value;
7631 t->specularscale *= t->specularscalemod;
7632 t->specularpower *= t->specularpowermod;
7634 // lightmaps mode looks bad with dlights using actual texturing, so turn
7635 // off the colormap and glossmap, but leave the normalmap on as it still
7636 // accurately represents the shading involved
7637 if (gl_lightmaps.integer)
7639 t->basetexture = r_texture_grey128;
7640 t->pantstexture = r_texture_black;
7641 t->shirttexture = r_texture_black;
7642 t->nmaptexture = r_texture_blanknormalmap;
7643 t->glosstexture = r_texture_black;
7644 t->glowtexture = NULL;
7645 t->fogtexture = NULL;
7646 t->reflectmasktexture = NULL;
7647 t->backgroundbasetexture = NULL;
7648 t->backgroundnmaptexture = r_texture_blanknormalmap;
7649 t->backgroundglosstexture = r_texture_black;
7650 t->backgroundglowtexture = NULL;
7651 t->specularscale = 0;
7652 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7655 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7656 VectorClear(t->dlightcolor);
7657 t->currentnumlayers = 0;
7658 if (t->currentmaterialflags & MATERIALFLAG_WALL)
7660 int blendfunc1, blendfunc2;
7662 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7664 blendfunc1 = GL_SRC_ALPHA;
7665 blendfunc2 = GL_ONE;
7667 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7669 blendfunc1 = GL_SRC_ALPHA;
7670 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7672 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7674 blendfunc1 = t->customblendfunc[0];
7675 blendfunc2 = t->customblendfunc[1];
7679 blendfunc1 = GL_ONE;
7680 blendfunc2 = GL_ZERO;
7682 // don't colormod evilblend textures
7683 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7684 VectorSet(t->lightmapcolor, 1, 1, 1);
7685 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7686 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7688 // fullbright is not affected by r_refdef.lightmapintensity
7689 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]);
7690 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7691 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]);
7692 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7693 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]);
7697 vec3_t ambientcolor;
7699 // set the color tint used for lights affecting this surface
7700 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7702 // q3bsp has no lightmap updates, so the lightstylevalue that
7703 // would normally be baked into the lightmap must be
7704 // applied to the color
7705 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7706 if (model->type == mod_brushq3)
7707 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7708 colorscale *= r_refdef.lightmapintensity;
7709 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7710 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7711 // basic lit geometry
7712 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]);
7713 // add pants/shirt if needed
7714 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7715 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]);
7716 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7717 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]);
7718 // now add ambient passes if needed
7719 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7721 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]);
7722 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7723 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]);
7724 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7725 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]);
7728 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7729 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]);
7730 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7732 // if this is opaque use alpha blend which will darken the earlier
7735 // if this is an alpha blended material, all the earlier passes
7736 // were darkened by fog already, so we only need to add the fog
7737 // color ontop through the fog mask texture
7739 // if this is an additive blended material, all the earlier passes
7740 // were darkened by fog already, and we should not add fog color
7741 // (because the background was not darkened, there is no fog color
7742 // that was lost behind it).
7743 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]);
7747 return t->currentframe;
7750 rsurfacestate_t rsurface;
7752 void RSurf_ActiveWorldEntity(void)
7754 dp_model_t *model = r_refdef.scene.worldmodel;
7755 //if (rsurface.entity == r_refdef.scene.worldentity)
7757 rsurface.entity = r_refdef.scene.worldentity;
7758 rsurface.skeleton = NULL;
7759 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7760 rsurface.ent_skinnum = 0;
7761 rsurface.ent_qwskin = -1;
7762 rsurface.ent_shadertime = 0;
7763 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7764 rsurface.matrix = identitymatrix;
7765 rsurface.inversematrix = identitymatrix;
7766 rsurface.matrixscale = 1;
7767 rsurface.inversematrixscale = 1;
7768 R_EntityMatrix(&identitymatrix);
7769 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7770 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7771 rsurface.fograngerecip = r_refdef.fograngerecip;
7772 rsurface.fogheightfade = r_refdef.fogheightfade;
7773 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7774 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7775 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7776 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7777 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7778 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7779 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7780 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7781 rsurface.colormod[3] = 1;
7782 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);
7783 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7784 rsurface.frameblend[0].lerp = 1;
7785 rsurface.ent_alttextures = false;
7786 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7787 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7788 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7789 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7790 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7791 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7792 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7793 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7794 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7795 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7796 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7797 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7798 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7799 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7800 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7801 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7802 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7803 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7804 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7805 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7806 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7807 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7808 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7809 rsurface.modelelement3i = model->surfmesh.data_element3i;
7810 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7811 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7812 rsurface.modelelement3s = model->surfmesh.data_element3s;
7813 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7814 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7815 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7816 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7817 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7818 rsurface.modelsurfaces = model->data_surfaces;
7819 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7820 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7821 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7822 rsurface.modelgeneratedvertex = false;
7823 rsurface.batchgeneratedvertex = false;
7824 rsurface.batchfirstvertex = 0;
7825 rsurface.batchnumvertices = 0;
7826 rsurface.batchfirsttriangle = 0;
7827 rsurface.batchnumtriangles = 0;
7828 rsurface.batchvertex3f = NULL;
7829 rsurface.batchvertex3f_vertexbuffer = NULL;
7830 rsurface.batchvertex3f_bufferoffset = 0;
7831 rsurface.batchsvector3f = NULL;
7832 rsurface.batchsvector3f_vertexbuffer = NULL;
7833 rsurface.batchsvector3f_bufferoffset = 0;
7834 rsurface.batchtvector3f = NULL;
7835 rsurface.batchtvector3f_vertexbuffer = NULL;
7836 rsurface.batchtvector3f_bufferoffset = 0;
7837 rsurface.batchnormal3f = NULL;
7838 rsurface.batchnormal3f_vertexbuffer = NULL;
7839 rsurface.batchnormal3f_bufferoffset = 0;
7840 rsurface.batchlightmapcolor4f = NULL;
7841 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7842 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7843 rsurface.batchtexcoordtexture2f = NULL;
7844 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7845 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7846 rsurface.batchtexcoordlightmap2f = NULL;
7847 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7848 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7849 rsurface.batchvertexmesh = NULL;
7850 rsurface.batchvertexmeshbuffer = NULL;
7851 rsurface.batchvertex3fbuffer = NULL;
7852 rsurface.batchelement3i = NULL;
7853 rsurface.batchelement3i_indexbuffer = NULL;
7854 rsurface.batchelement3i_bufferoffset = 0;
7855 rsurface.batchelement3s = NULL;
7856 rsurface.batchelement3s_indexbuffer = NULL;
7857 rsurface.batchelement3s_bufferoffset = 0;
7858 rsurface.passcolor4f = NULL;
7859 rsurface.passcolor4f_vertexbuffer = NULL;
7860 rsurface.passcolor4f_bufferoffset = 0;
7863 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7865 dp_model_t *model = ent->model;
7866 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7868 rsurface.entity = (entity_render_t *)ent;
7869 rsurface.skeleton = ent->skeleton;
7870 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7871 rsurface.ent_skinnum = ent->skinnum;
7872 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;
7873 rsurface.ent_shadertime = ent->shadertime;
7874 rsurface.ent_flags = ent->flags;
7875 rsurface.matrix = ent->matrix;
7876 rsurface.inversematrix = ent->inversematrix;
7877 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7878 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7879 R_EntityMatrix(&rsurface.matrix);
7880 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7881 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7882 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7883 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7884 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7885 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7886 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7887 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7888 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7889 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7890 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7891 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7892 rsurface.colormod[3] = ent->alpha;
7893 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7894 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7895 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7896 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7897 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7898 if (ent->model->brush.submodel && !prepass)
7900 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7901 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7903 if (model->surfmesh.isanimated && model->AnimateVertices)
7905 if (ent->animcache_vertex3f)
7907 rsurface.modelvertex3f = ent->animcache_vertex3f;
7908 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7909 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7910 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7911 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7912 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
7913 rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
7915 else if (wanttangents)
7917 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7918 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7919 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7920 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7921 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7922 rsurface.modelvertexmesh = NULL;
7923 rsurface.modelvertexmeshbuffer = NULL;
7924 rsurface.modelvertex3fbuffer = NULL;
7926 else if (wantnormals)
7928 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7929 rsurface.modelsvector3f = NULL;
7930 rsurface.modeltvector3f = NULL;
7931 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7932 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
7933 rsurface.modelvertexmesh = NULL;
7934 rsurface.modelvertexmeshbuffer = NULL;
7935 rsurface.modelvertex3fbuffer = NULL;
7939 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7940 rsurface.modelsvector3f = NULL;
7941 rsurface.modeltvector3f = NULL;
7942 rsurface.modelnormal3f = NULL;
7943 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
7944 rsurface.modelvertexmesh = NULL;
7945 rsurface.modelvertexmeshbuffer = NULL;
7946 rsurface.modelvertex3fbuffer = NULL;
7948 rsurface.modelvertex3f_vertexbuffer = 0;
7949 rsurface.modelvertex3f_bufferoffset = 0;
7950 rsurface.modelsvector3f_vertexbuffer = 0;
7951 rsurface.modelsvector3f_bufferoffset = 0;
7952 rsurface.modeltvector3f_vertexbuffer = 0;
7953 rsurface.modeltvector3f_bufferoffset = 0;
7954 rsurface.modelnormal3f_vertexbuffer = 0;
7955 rsurface.modelnormal3f_bufferoffset = 0;
7956 rsurface.modelgeneratedvertex = true;
7960 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7961 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7962 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7963 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7964 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7965 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7966 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7967 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7968 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7969 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7970 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7971 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7972 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7973 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7974 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7975 rsurface.modelgeneratedvertex = false;
7977 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7978 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7979 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7980 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7981 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7982 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7983 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7984 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7985 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7986 rsurface.modelelement3i = model->surfmesh.data_element3i;
7987 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7988 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7989 rsurface.modelelement3s = model->surfmesh.data_element3s;
7990 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7991 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7992 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7993 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7994 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7995 rsurface.modelsurfaces = model->data_surfaces;
7996 rsurface.batchgeneratedvertex = false;
7997 rsurface.batchfirstvertex = 0;
7998 rsurface.batchnumvertices = 0;
7999 rsurface.batchfirsttriangle = 0;
8000 rsurface.batchnumtriangles = 0;
8001 rsurface.batchvertex3f = NULL;
8002 rsurface.batchvertex3f_vertexbuffer = NULL;
8003 rsurface.batchvertex3f_bufferoffset = 0;
8004 rsurface.batchsvector3f = NULL;
8005 rsurface.batchsvector3f_vertexbuffer = NULL;
8006 rsurface.batchsvector3f_bufferoffset = 0;
8007 rsurface.batchtvector3f = NULL;
8008 rsurface.batchtvector3f_vertexbuffer = NULL;
8009 rsurface.batchtvector3f_bufferoffset = 0;
8010 rsurface.batchnormal3f = NULL;
8011 rsurface.batchnormal3f_vertexbuffer = NULL;
8012 rsurface.batchnormal3f_bufferoffset = 0;
8013 rsurface.batchlightmapcolor4f = NULL;
8014 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8015 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8016 rsurface.batchtexcoordtexture2f = NULL;
8017 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8018 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8019 rsurface.batchtexcoordlightmap2f = NULL;
8020 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8021 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8022 rsurface.batchvertexmesh = NULL;
8023 rsurface.batchvertexmeshbuffer = NULL;
8024 rsurface.batchvertex3fbuffer = NULL;
8025 rsurface.batchelement3i = NULL;
8026 rsurface.batchelement3i_indexbuffer = NULL;
8027 rsurface.batchelement3i_bufferoffset = 0;
8028 rsurface.batchelement3s = NULL;
8029 rsurface.batchelement3s_indexbuffer = NULL;
8030 rsurface.batchelement3s_bufferoffset = 0;
8031 rsurface.passcolor4f = NULL;
8032 rsurface.passcolor4f_vertexbuffer = NULL;
8033 rsurface.passcolor4f_bufferoffset = 0;
8036 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)
8038 rsurface.entity = r_refdef.scene.worldentity;
8039 rsurface.skeleton = NULL;
8040 rsurface.ent_skinnum = 0;
8041 rsurface.ent_qwskin = -1;
8042 rsurface.ent_shadertime = shadertime;
8043 rsurface.ent_flags = entflags;
8044 rsurface.modelnumvertices = numvertices;
8045 rsurface.modelnumtriangles = numtriangles;
8046 rsurface.matrix = *matrix;
8047 rsurface.inversematrix = *inversematrix;
8048 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8049 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8050 R_EntityMatrix(&rsurface.matrix);
8051 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8052 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8053 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8054 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8055 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8056 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8057 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8058 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8059 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8060 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8061 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8062 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8063 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);
8064 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8065 rsurface.frameblend[0].lerp = 1;
8066 rsurface.ent_alttextures = false;
8067 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8068 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8071 rsurface.modelvertex3f = (float *)vertex3f;
8072 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8073 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8074 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8076 else if (wantnormals)
8078 rsurface.modelvertex3f = (float *)vertex3f;
8079 rsurface.modelsvector3f = NULL;
8080 rsurface.modeltvector3f = NULL;
8081 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8085 rsurface.modelvertex3f = (float *)vertex3f;
8086 rsurface.modelsvector3f = NULL;
8087 rsurface.modeltvector3f = NULL;
8088 rsurface.modelnormal3f = NULL;
8090 rsurface.modelvertexmesh = NULL;
8091 rsurface.modelvertexmeshbuffer = NULL;
8092 rsurface.modelvertex3fbuffer = NULL;
8093 rsurface.modelvertex3f_vertexbuffer = 0;
8094 rsurface.modelvertex3f_bufferoffset = 0;
8095 rsurface.modelsvector3f_vertexbuffer = 0;
8096 rsurface.modelsvector3f_bufferoffset = 0;
8097 rsurface.modeltvector3f_vertexbuffer = 0;
8098 rsurface.modeltvector3f_bufferoffset = 0;
8099 rsurface.modelnormal3f_vertexbuffer = 0;
8100 rsurface.modelnormal3f_bufferoffset = 0;
8101 rsurface.modelgeneratedvertex = true;
8102 rsurface.modellightmapcolor4f = (float *)color4f;
8103 rsurface.modellightmapcolor4f_vertexbuffer = 0;
8104 rsurface.modellightmapcolor4f_bufferoffset = 0;
8105 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
8106 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8107 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8108 rsurface.modeltexcoordlightmap2f = NULL;
8109 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8110 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8111 rsurface.modelelement3i = (int *)element3i;
8112 rsurface.modelelement3i_indexbuffer = NULL;
8113 rsurface.modelelement3i_bufferoffset = 0;
8114 rsurface.modelelement3s = (unsigned short *)element3s;
8115 rsurface.modelelement3s_indexbuffer = NULL;
8116 rsurface.modelelement3s_bufferoffset = 0;
8117 rsurface.modellightmapoffsets = NULL;
8118 rsurface.modelsurfaces = NULL;
8119 rsurface.batchgeneratedvertex = false;
8120 rsurface.batchfirstvertex = 0;
8121 rsurface.batchnumvertices = 0;
8122 rsurface.batchfirsttriangle = 0;
8123 rsurface.batchnumtriangles = 0;
8124 rsurface.batchvertex3f = NULL;
8125 rsurface.batchvertex3f_vertexbuffer = NULL;
8126 rsurface.batchvertex3f_bufferoffset = 0;
8127 rsurface.batchsvector3f = NULL;
8128 rsurface.batchsvector3f_vertexbuffer = NULL;
8129 rsurface.batchsvector3f_bufferoffset = 0;
8130 rsurface.batchtvector3f = NULL;
8131 rsurface.batchtvector3f_vertexbuffer = NULL;
8132 rsurface.batchtvector3f_bufferoffset = 0;
8133 rsurface.batchnormal3f = NULL;
8134 rsurface.batchnormal3f_vertexbuffer = NULL;
8135 rsurface.batchnormal3f_bufferoffset = 0;
8136 rsurface.batchlightmapcolor4f = NULL;
8137 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8138 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8139 rsurface.batchtexcoordtexture2f = NULL;
8140 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8141 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8142 rsurface.batchtexcoordlightmap2f = NULL;
8143 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8144 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8145 rsurface.batchvertexmesh = NULL;
8146 rsurface.batchvertexmeshbuffer = NULL;
8147 rsurface.batchvertex3fbuffer = NULL;
8148 rsurface.batchelement3i = NULL;
8149 rsurface.batchelement3i_indexbuffer = NULL;
8150 rsurface.batchelement3i_bufferoffset = 0;
8151 rsurface.batchelement3s = NULL;
8152 rsurface.batchelement3s_indexbuffer = NULL;
8153 rsurface.batchelement3s_bufferoffset = 0;
8154 rsurface.passcolor4f = NULL;
8155 rsurface.passcolor4f_vertexbuffer = NULL;
8156 rsurface.passcolor4f_bufferoffset = 0;
8158 if (rsurface.modelnumvertices && rsurface.modelelement3i)
8160 if ((wantnormals || wanttangents) && !normal3f)
8162 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8163 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8165 if (wanttangents && !svector3f)
8167 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8168 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8169 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8174 float RSurf_FogPoint(const float *v)
8176 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8177 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8178 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8179 float FogHeightFade = r_refdef.fogheightfade;
8181 unsigned int fogmasktableindex;
8182 if (r_refdef.fogplaneviewabove)
8183 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8185 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8186 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8187 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8190 float RSurf_FogVertex(const float *v)
8192 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8193 float FogPlaneViewDist = rsurface.fogplaneviewdist;
8194 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8195 float FogHeightFade = rsurface.fogheightfade;
8197 unsigned int fogmasktableindex;
8198 if (r_refdef.fogplaneviewabove)
8199 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8201 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8202 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8203 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8206 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8209 for (i = 0;i < numelements;i++)
8210 outelement3i[i] = inelement3i[i] + adjust;
8213 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8214 extern cvar_t gl_vbo;
8215 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8223 int surfacefirsttriangle;
8224 int surfacenumtriangles;
8225 int surfacefirstvertex;
8226 int surfaceendvertex;
8227 int surfacenumvertices;
8228 int batchnumvertices;
8229 int batchnumtriangles;
8233 qboolean dynamicvertex;
8237 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8239 q3shaderinfo_deform_t *deform;
8240 const msurface_t *surface, *firstsurface;
8241 r_vertexmesh_t *vertexmesh;
8242 if (!texturenumsurfaces)
8244 // find vertex range of this surface batch
8246 firstsurface = texturesurfacelist[0];
8247 firsttriangle = firstsurface->num_firsttriangle;
8248 batchnumvertices = 0;
8249 batchnumtriangles = 0;
8250 firstvertex = endvertex = firstsurface->num_firstvertex;
8251 for (i = 0;i < texturenumsurfaces;i++)
8253 surface = texturesurfacelist[i];
8254 if (surface != firstsurface + i)
8256 surfacefirstvertex = surface->num_firstvertex;
8257 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8258 surfacenumvertices = surface->num_vertices;
8259 surfacenumtriangles = surface->num_triangles;
8260 if (firstvertex > surfacefirstvertex)
8261 firstvertex = surfacefirstvertex;
8262 if (endvertex < surfaceendvertex)
8263 endvertex = surfaceendvertex;
8264 batchnumvertices += surfacenumvertices;
8265 batchnumtriangles += surfacenumtriangles;
8268 // we now know the vertex range used, and if there are any gaps in it
8269 rsurface.batchfirstvertex = firstvertex;
8270 rsurface.batchnumvertices = endvertex - firstvertex;
8271 rsurface.batchfirsttriangle = firsttriangle;
8272 rsurface.batchnumtriangles = batchnumtriangles;
8274 // this variable holds flags for which properties have been updated that
8275 // may require regenerating vertexmesh array...
8278 // check if any dynamic vertex processing must occur
8279 dynamicvertex = false;
8281 // if there is a chance of animated vertex colors, it's a dynamic batch
8282 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8284 dynamicvertex = true;
8285 batchneed |= BATCHNEED_NOGAPS;
8286 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8289 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8291 switch (deform->deform)
8294 case Q3DEFORM_PROJECTIONSHADOW:
8295 case Q3DEFORM_TEXT0:
8296 case Q3DEFORM_TEXT1:
8297 case Q3DEFORM_TEXT2:
8298 case Q3DEFORM_TEXT3:
8299 case Q3DEFORM_TEXT4:
8300 case Q3DEFORM_TEXT5:
8301 case Q3DEFORM_TEXT6:
8302 case Q3DEFORM_TEXT7:
8305 case Q3DEFORM_AUTOSPRITE:
8306 dynamicvertex = true;
8307 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8308 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8310 case Q3DEFORM_AUTOSPRITE2:
8311 dynamicvertex = true;
8312 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8313 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8315 case Q3DEFORM_NORMAL:
8316 dynamicvertex = true;
8317 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8318 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8321 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8322 break; // if wavefunc is a nop, ignore this transform
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;
8327 case Q3DEFORM_BULGE:
8328 dynamicvertex = true;
8329 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8330 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8333 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8334 break; // if wavefunc is a nop, ignore this transform
8335 dynamicvertex = true;
8336 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8337 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8341 switch(rsurface.texture->tcgen.tcgen)
8344 case Q3TCGEN_TEXTURE:
8346 case Q3TCGEN_LIGHTMAP:
8347 dynamicvertex = true;
8348 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8349 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8351 case Q3TCGEN_VECTOR:
8352 dynamicvertex = true;
8353 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8354 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8356 case Q3TCGEN_ENVIRONMENT:
8357 dynamicvertex = true;
8358 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8359 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8362 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8364 dynamicvertex = true;
8365 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8366 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8369 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8371 dynamicvertex = true;
8372 batchneed |= BATCHNEED_NOGAPS;
8373 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8376 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8378 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8379 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
8380 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
8381 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
8382 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8383 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8384 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8387 // when the model data has no vertex buffer (dynamic mesh), we need to
8389 if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8390 batchneed |= BATCHNEED_NOGAPS;
8392 // if needsupdate, we have to do a dynamic vertex batch for sure
8393 if (needsupdate & batchneed)
8394 dynamicvertex = true;
8396 // see if we need to build vertexmesh from arrays
8397 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8398 dynamicvertex = true;
8400 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8401 // also some drivers strongly dislike firstvertex
8402 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8403 dynamicvertex = true;
8405 rsurface.batchvertex3f = rsurface.modelvertex3f;
8406 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8407 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8408 rsurface.batchsvector3f = rsurface.modelsvector3f;
8409 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8410 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8411 rsurface.batchtvector3f = rsurface.modeltvector3f;
8412 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8413 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8414 rsurface.batchnormal3f = rsurface.modelnormal3f;
8415 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8416 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8417 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8418 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
8419 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8420 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8421 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
8422 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
8423 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8424 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8425 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8426 rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8427 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8428 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8429 rsurface.batchelement3i = rsurface.modelelement3i;
8430 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8431 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8432 rsurface.batchelement3s = rsurface.modelelement3s;
8433 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8434 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8436 // if any dynamic vertex processing has to occur in software, we copy the
8437 // entire surface list together before processing to rebase the vertices
8438 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8440 // if any gaps exist and we do not have a static vertex buffer, we have to
8441 // copy the surface list together to avoid wasting upload bandwidth on the
8442 // vertices in the gaps.
8444 // if gaps exist and we have a static vertex buffer, we still have to
8445 // combine the index buffer ranges into one dynamic index buffer.
8447 // in all cases we end up with data that can be drawn in one call.
8451 // static vertex data, just set pointers...
8452 rsurface.batchgeneratedvertex = false;
8453 // if there are gaps, we want to build a combined index buffer,
8454 // otherwise use the original static buffer with an appropriate offset
8457 // build a new triangle elements array for this batch
8458 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8459 rsurface.batchfirsttriangle = 0;
8461 for (i = 0;i < texturenumsurfaces;i++)
8463 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8464 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8465 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8466 numtriangles += surfacenumtriangles;
8468 rsurface.batchelement3i_indexbuffer = NULL;
8469 rsurface.batchelement3i_bufferoffset = 0;
8470 rsurface.batchelement3s = NULL;
8471 rsurface.batchelement3s_indexbuffer = NULL;
8472 rsurface.batchelement3s_bufferoffset = 0;
8473 if (endvertex <= 65536)
8475 // make a 16bit (unsigned short) index array if possible
8476 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8477 for (i = 0;i < numtriangles*3;i++)
8478 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8484 // something needs software processing, do it for real...
8485 // we only directly handle separate array data in this case and then
8486 // generate interleaved data if needed...
8487 rsurface.batchgeneratedvertex = true;
8489 // now copy the vertex data into a combined array and make an index array
8490 // (this is what Quake3 does all the time)
8491 //if (gaps || rsurface.batchfirstvertex)
8493 rsurface.batchvertex3fbuffer = NULL;
8494 rsurface.batchvertexmesh = NULL;
8495 rsurface.batchvertexmeshbuffer = NULL;
8496 rsurface.batchvertex3f = NULL;
8497 rsurface.batchvertex3f_vertexbuffer = NULL;
8498 rsurface.batchvertex3f_bufferoffset = 0;
8499 rsurface.batchsvector3f = NULL;
8500 rsurface.batchsvector3f_vertexbuffer = NULL;
8501 rsurface.batchsvector3f_bufferoffset = 0;
8502 rsurface.batchtvector3f = NULL;
8503 rsurface.batchtvector3f_vertexbuffer = NULL;
8504 rsurface.batchtvector3f_bufferoffset = 0;
8505 rsurface.batchnormal3f = NULL;
8506 rsurface.batchnormal3f_vertexbuffer = NULL;
8507 rsurface.batchnormal3f_bufferoffset = 0;
8508 rsurface.batchlightmapcolor4f = NULL;
8509 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8510 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8511 rsurface.batchtexcoordtexture2f = NULL;
8512 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8513 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8514 rsurface.batchtexcoordlightmap2f = NULL;
8515 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8516 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8517 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8518 rsurface.batchelement3i_indexbuffer = NULL;
8519 rsurface.batchelement3i_bufferoffset = 0;
8520 rsurface.batchelement3s = NULL;
8521 rsurface.batchelement3s_indexbuffer = NULL;
8522 rsurface.batchelement3s_bufferoffset = 0;
8523 // we'll only be setting up certain arrays as needed
8524 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8525 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8526 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8527 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8528 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8529 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8530 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8532 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8533 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8535 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8536 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8537 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8538 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8539 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8540 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8543 for (i = 0;i < texturenumsurfaces;i++)
8545 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8546 surfacenumvertices = texturesurfacelist[i]->num_vertices;
8547 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8548 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8549 // copy only the data requested
8550 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8551 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8552 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8554 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8555 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8556 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
8557 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8558 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
8560 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8561 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8563 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
8564 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8565 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
8566 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8567 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
8568 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8570 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8571 numvertices += surfacenumvertices;
8572 numtriangles += surfacenumtriangles;
8575 // generate a 16bit index array as well if possible
8576 // (in general, dynamic batches fit)
8577 if (numvertices <= 65536)
8579 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8580 for (i = 0;i < numtriangles*3;i++)
8581 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8584 // since we've copied everything, the batch now starts at 0
8585 rsurface.batchfirstvertex = 0;
8586 rsurface.batchnumvertices = batchnumvertices;
8587 rsurface.batchfirsttriangle = 0;
8588 rsurface.batchnumtriangles = batchnumtriangles;
8591 // q1bsp surfaces rendered in vertex color mode have to have colors
8592 // calculated based on lightstyles
8593 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8595 // generate color arrays for the surfaces in this list
8600 const unsigned char *lm;
8601 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8602 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8603 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8605 for (i = 0;i < texturenumsurfaces;i++)
8607 surface = texturesurfacelist[i];
8608 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8609 surfacenumvertices = surface->num_vertices;
8610 if (surface->lightmapinfo->samples)
8612 for (j = 0;j < surfacenumvertices;j++)
8614 lm = surface->lightmapinfo->samples + offsets[j];
8615 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8616 VectorScale(lm, scale, c);
8617 if (surface->lightmapinfo->styles[1] != 255)
8619 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8621 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8622 VectorMA(c, scale, lm, c);
8623 if (surface->lightmapinfo->styles[2] != 255)
8626 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8627 VectorMA(c, scale, lm, c);
8628 if (surface->lightmapinfo->styles[3] != 255)
8631 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8632 VectorMA(c, scale, lm, c);
8639 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);
8645 for (j = 0;j < surfacenumvertices;j++)
8647 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8654 // if vertices are deformed (sprite flares and things in maps, possibly
8655 // water waves, bulges and other deformations), modify the copied vertices
8657 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8659 switch (deform->deform)
8662 case Q3DEFORM_PROJECTIONSHADOW:
8663 case Q3DEFORM_TEXT0:
8664 case Q3DEFORM_TEXT1:
8665 case Q3DEFORM_TEXT2:
8666 case Q3DEFORM_TEXT3:
8667 case Q3DEFORM_TEXT4:
8668 case Q3DEFORM_TEXT5:
8669 case Q3DEFORM_TEXT6:
8670 case Q3DEFORM_TEXT7:
8673 case Q3DEFORM_AUTOSPRITE:
8674 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8675 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8676 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8677 VectorNormalize(newforward);
8678 VectorNormalize(newright);
8679 VectorNormalize(newup);
8680 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8681 // rsurface.batchvertex3f_vertexbuffer = NULL;
8682 // rsurface.batchvertex3f_bufferoffset = 0;
8683 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8684 // rsurface.batchsvector3f_vertexbuffer = NULL;
8685 // rsurface.batchsvector3f_bufferoffset = 0;
8686 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8687 // rsurface.batchtvector3f_vertexbuffer = NULL;
8688 // rsurface.batchtvector3f_bufferoffset = 0;
8689 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8690 // rsurface.batchnormal3f_vertexbuffer = NULL;
8691 // rsurface.batchnormal3f_bufferoffset = 0;
8692 // a single autosprite surface can contain multiple sprites...
8693 for (j = 0;j < batchnumvertices - 3;j += 4)
8695 VectorClear(center);
8696 for (i = 0;i < 4;i++)
8697 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8698 VectorScale(center, 0.25f, center);
8699 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8700 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8701 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8702 for (i = 0;i < 4;i++)
8704 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8705 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8708 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8709 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8710 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);
8712 case Q3DEFORM_AUTOSPRITE2:
8713 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8714 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8715 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8716 VectorNormalize(newforward);
8717 VectorNormalize(newright);
8718 VectorNormalize(newup);
8719 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8720 // rsurface.batchvertex3f_vertexbuffer = NULL;
8721 // rsurface.batchvertex3f_bufferoffset = 0;
8723 const float *v1, *v2;
8733 memset(shortest, 0, sizeof(shortest));
8734 // a single autosprite surface can contain multiple sprites...
8735 for (j = 0;j < batchnumvertices - 3;j += 4)
8737 VectorClear(center);
8738 for (i = 0;i < 4;i++)
8739 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8740 VectorScale(center, 0.25f, center);
8741 // find the two shortest edges, then use them to define the
8742 // axis vectors for rotating around the central axis
8743 for (i = 0;i < 6;i++)
8745 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8746 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8747 l = VectorDistance2(v1, v2);
8748 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8750 l += (1.0f / 1024.0f);
8751 if (shortest[0].length2 > l || i == 0)
8753 shortest[1] = shortest[0];
8754 shortest[0].length2 = l;
8755 shortest[0].v1 = v1;
8756 shortest[0].v2 = v2;
8758 else if (shortest[1].length2 > l || i == 1)
8760 shortest[1].length2 = l;
8761 shortest[1].v1 = v1;
8762 shortest[1].v2 = v2;
8765 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8766 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8767 // this calculates the right vector from the shortest edge
8768 // and the up vector from the edge midpoints
8769 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8770 VectorNormalize(right);
8771 VectorSubtract(end, start, up);
8772 VectorNormalize(up);
8773 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8774 VectorSubtract(rsurface.localvieworigin, center, forward);
8775 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8776 VectorNegate(forward, forward);
8777 VectorReflect(forward, 0, up, forward);
8778 VectorNormalize(forward);
8779 CrossProduct(up, forward, newright);
8780 VectorNormalize(newright);
8781 // rotate the quad around the up axis vector, this is made
8782 // especially easy by the fact we know the quad is flat,
8783 // so we only have to subtract the center position and
8784 // measure distance along the right vector, and then
8785 // multiply that by the newright vector and add back the
8787 // we also need to subtract the old position to undo the
8788 // displacement from the center, which we do with a
8789 // DotProduct, the subtraction/addition of center is also
8790 // optimized into DotProducts here
8791 l = DotProduct(right, center);
8792 for (i = 0;i < 4;i++)
8794 v1 = rsurface.batchvertex3f + 3*(j+i);
8795 f = DotProduct(right, v1) - l;
8796 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8800 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8802 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8803 // rsurface.batchnormal3f_vertexbuffer = NULL;
8804 // rsurface.batchnormal3f_bufferoffset = 0;
8805 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8807 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8809 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8810 // rsurface.batchsvector3f_vertexbuffer = NULL;
8811 // rsurface.batchsvector3f_bufferoffset = 0;
8812 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8813 // rsurface.batchtvector3f_vertexbuffer = NULL;
8814 // rsurface.batchtvector3f_bufferoffset = 0;
8815 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);
8818 case Q3DEFORM_NORMAL:
8819 // deform the normals to make reflections wavey
8820 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8821 rsurface.batchnormal3f_vertexbuffer = NULL;
8822 rsurface.batchnormal3f_bufferoffset = 0;
8823 for (j = 0;j < batchnumvertices;j++)
8826 float *normal = rsurface.batchnormal3f + 3*j;
8827 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8828 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8829 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]);
8830 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]);
8831 VectorNormalize(normal);
8833 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8835 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8836 // rsurface.batchsvector3f_vertexbuffer = NULL;
8837 // rsurface.batchsvector3f_bufferoffset = 0;
8838 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8839 // rsurface.batchtvector3f_vertexbuffer = NULL;
8840 // rsurface.batchtvector3f_bufferoffset = 0;
8841 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);
8845 // deform vertex array to make wavey water and flags and such
8846 waveparms[0] = deform->waveparms[0];
8847 waveparms[1] = deform->waveparms[1];
8848 waveparms[2] = deform->waveparms[2];
8849 waveparms[3] = deform->waveparms[3];
8850 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8851 break; // if wavefunc is a nop, don't make a dynamic vertex array
8852 // this is how a divisor of vertex influence on deformation
8853 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8854 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8855 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8856 // rsurface.batchvertex3f_vertexbuffer = NULL;
8857 // rsurface.batchvertex3f_bufferoffset = 0;
8858 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8859 // rsurface.batchnormal3f_vertexbuffer = NULL;
8860 // rsurface.batchnormal3f_bufferoffset = 0;
8861 for (j = 0;j < batchnumvertices;j++)
8863 // if the wavefunc depends on time, evaluate it per-vertex
8866 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8867 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8869 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8871 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8872 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8873 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8875 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8876 // rsurface.batchsvector3f_vertexbuffer = NULL;
8877 // rsurface.batchsvector3f_bufferoffset = 0;
8878 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8879 // rsurface.batchtvector3f_vertexbuffer = NULL;
8880 // rsurface.batchtvector3f_bufferoffset = 0;
8881 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);
8884 case Q3DEFORM_BULGE:
8885 // deform vertex array to make the surface have moving bulges
8886 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8887 // rsurface.batchvertex3f_vertexbuffer = NULL;
8888 // rsurface.batchvertex3f_bufferoffset = 0;
8889 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8890 // rsurface.batchnormal3f_vertexbuffer = NULL;
8891 // rsurface.batchnormal3f_bufferoffset = 0;
8892 for (j = 0;j < batchnumvertices;j++)
8894 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
8895 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8897 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8898 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8899 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8901 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8902 // rsurface.batchsvector3f_vertexbuffer = NULL;
8903 // rsurface.batchsvector3f_bufferoffset = 0;
8904 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8905 // rsurface.batchtvector3f_vertexbuffer = NULL;
8906 // rsurface.batchtvector3f_bufferoffset = 0;
8907 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);
8911 // deform vertex array
8912 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8913 break; // if wavefunc is a nop, don't make a dynamic vertex array
8914 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8915 VectorScale(deform->parms, scale, waveparms);
8916 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8917 // rsurface.batchvertex3f_vertexbuffer = NULL;
8918 // rsurface.batchvertex3f_bufferoffset = 0;
8919 for (j = 0;j < batchnumvertices;j++)
8920 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8925 // generate texcoords based on the chosen texcoord source
8926 switch(rsurface.texture->tcgen.tcgen)
8929 case Q3TCGEN_TEXTURE:
8931 case Q3TCGEN_LIGHTMAP:
8932 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8933 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8934 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8935 if (rsurface.batchtexcoordlightmap2f)
8936 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
8938 case Q3TCGEN_VECTOR:
8939 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8940 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8941 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8942 for (j = 0;j < batchnumvertices;j++)
8944 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
8945 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
8948 case Q3TCGEN_ENVIRONMENT:
8949 // make environment reflections using a spheremap
8950 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8951 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8952 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8953 for (j = 0;j < batchnumvertices;j++)
8955 // identical to Q3A's method, but executed in worldspace so
8956 // carried models can be shiny too
8958 float viewer[3], d, reflected[3], worldreflected[3];
8960 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
8961 // VectorNormalize(viewer);
8963 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
8965 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
8966 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
8967 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
8968 // note: this is proportinal to viewer, so we can normalize later
8970 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
8971 VectorNormalize(worldreflected);
8973 // note: this sphere map only uses world x and z!
8974 // so positive and negative y will LOOK THE SAME.
8975 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
8976 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
8980 // the only tcmod that needs software vertex processing is turbulent, so
8981 // check for it here and apply the changes if needed
8982 // and we only support that as the first one
8983 // (handling a mixture of turbulent and other tcmods would be problematic
8984 // without punting it entirely to a software path)
8985 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8987 amplitude = rsurface.texture->tcmods[0].parms[1];
8988 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
8989 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8990 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8991 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8992 for (j = 0;j < batchnumvertices;j++)
8994 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);
8995 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
8999 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9001 // convert the modified arrays to vertex structs
9002 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9003 // rsurface.batchvertexmeshbuffer = NULL;
9004 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9005 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9006 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9007 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9008 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9009 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9010 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9012 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9014 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9015 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9018 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9019 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9020 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9021 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9022 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9023 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9024 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9025 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9026 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9030 void RSurf_DrawBatch(void)
9032 // sometimes a zero triangle surface (usually a degenerate patch) makes it
9033 // through the pipeline, killing it earlier in the pipeline would have
9034 // per-surface overhead rather than per-batch overhead, so it's best to
9035 // reject it here, before it hits glDraw.
9036 if (rsurface.batchnumtriangles == 0)
9039 // batch debugging code
9040 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9046 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9047 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9050 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9052 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9054 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9055 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);
9062 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);
9065 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9067 // pick the closest matching water plane
9068 int planeindex, vertexindex, bestplaneindex = -1;
9072 r_waterstate_waterplane_t *p;
9073 qboolean prepared = false;
9075 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9077 if(p->camera_entity != rsurface.texture->camera_entity)
9082 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9084 if(rsurface.batchnumvertices == 0)
9087 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9089 Matrix4x4_Transform(&rsurface.matrix, v, vert);
9090 d += fabs(PlaneDiff(vert, &p->plane));
9092 if (bestd > d || bestplaneindex < 0)
9095 bestplaneindex = planeindex;
9098 return bestplaneindex;
9099 // NOTE: this MAY return a totally unrelated water plane; we can ignore
9100 // this situation though, as it might be better to render single larger
9101 // batches with useless stuff (backface culled for example) than to
9102 // render multiple smaller batches
9105 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9108 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9109 rsurface.passcolor4f_vertexbuffer = 0;
9110 rsurface.passcolor4f_bufferoffset = 0;
9111 for (i = 0;i < rsurface.batchnumvertices;i++)
9112 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9115 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9122 if (rsurface.passcolor4f)
9124 // generate color arrays
9125 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9126 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9127 rsurface.passcolor4f_vertexbuffer = 0;
9128 rsurface.passcolor4f_bufferoffset = 0;
9129 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)
9131 f = RSurf_FogVertex(v);
9140 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9141 rsurface.passcolor4f_vertexbuffer = 0;
9142 rsurface.passcolor4f_bufferoffset = 0;
9143 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9145 f = RSurf_FogVertex(v);
9154 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9161 if (!rsurface.passcolor4f)
9163 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9164 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9165 rsurface.passcolor4f_vertexbuffer = 0;
9166 rsurface.passcolor4f_bufferoffset = 0;
9167 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)
9169 f = RSurf_FogVertex(v);
9170 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9171 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9172 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9177 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9182 if (!rsurface.passcolor4f)
9184 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9185 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9186 rsurface.passcolor4f_vertexbuffer = 0;
9187 rsurface.passcolor4f_bufferoffset = 0;
9188 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9197 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9202 if (!rsurface.passcolor4f)
9204 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9205 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9206 rsurface.passcolor4f_vertexbuffer = 0;
9207 rsurface.passcolor4f_bufferoffset = 0;
9208 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9210 c2[0] = c[0] + r_refdef.scene.ambient;
9211 c2[1] = c[1] + r_refdef.scene.ambient;
9212 c2[2] = c[2] + r_refdef.scene.ambient;
9217 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9220 rsurface.passcolor4f = NULL;
9221 rsurface.passcolor4f_vertexbuffer = 0;
9222 rsurface.passcolor4f_bufferoffset = 0;
9223 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9224 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9225 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9226 GL_Color(r, g, b, a);
9227 R_Mesh_TexBind(0, rsurface.lightmaptexture);
9231 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9233 // TODO: optimize applyfog && applycolor case
9234 // just apply fog if necessary, and tint the fog color array if necessary
9235 rsurface.passcolor4f = NULL;
9236 rsurface.passcolor4f_vertexbuffer = 0;
9237 rsurface.passcolor4f_bufferoffset = 0;
9238 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9239 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9240 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9241 GL_Color(r, g, b, a);
9245 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9248 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9249 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9250 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9251 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9252 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9253 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9254 GL_Color(r, g, b, a);
9258 static void RSurf_DrawBatch_GL11_ClampColor(void)
9263 if (!rsurface.passcolor4f)
9265 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9267 c2[0] = bound(0.0f, c1[0], 1.0f);
9268 c2[1] = bound(0.0f, c1[1], 1.0f);
9269 c2[2] = bound(0.0f, c1[2], 1.0f);
9270 c2[3] = bound(0.0f, c1[3], 1.0f);
9274 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9284 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9285 rsurface.passcolor4f_vertexbuffer = 0;
9286 rsurface.passcolor4f_bufferoffset = 0;
9287 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)
9289 f = -DotProduct(r_refdef.view.forward, n);
9291 f = f * 0.85 + 0.15; // work around so stuff won't get black
9292 f *= r_refdef.lightmapintensity;
9293 Vector4Set(c, f, f, f, 1);
9297 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9299 RSurf_DrawBatch_GL11_ApplyFakeLight();
9300 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9301 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9302 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9303 GL_Color(r, g, b, a);
9307 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9315 vec3_t ambientcolor;
9316 vec3_t diffusecolor;
9320 VectorCopy(rsurface.modellight_lightdir, lightdir);
9321 f = 0.5f * r_refdef.lightmapintensity;
9322 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9323 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9324 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9325 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9326 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9327 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9329 if (VectorLength2(diffusecolor) > 0)
9331 // q3-style directional shading
9332 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9333 rsurface.passcolor4f_vertexbuffer = 0;
9334 rsurface.passcolor4f_bufferoffset = 0;
9335 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)
9337 if ((f = DotProduct(n, lightdir)) > 0)
9338 VectorMA(ambientcolor, f, diffusecolor, c);
9340 VectorCopy(ambientcolor, c);
9347 *applycolor = false;
9351 *r = ambientcolor[0];
9352 *g = ambientcolor[1];
9353 *b = ambientcolor[2];
9354 rsurface.passcolor4f = NULL;
9355 rsurface.passcolor4f_vertexbuffer = 0;
9356 rsurface.passcolor4f_bufferoffset = 0;
9360 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9362 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9363 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9364 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9365 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9366 GL_Color(r, g, b, a);
9370 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9378 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9379 rsurface.passcolor4f_vertexbuffer = 0;
9380 rsurface.passcolor4f_bufferoffset = 0;
9382 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9384 f = 1 - RSurf_FogVertex(v);
9392 void RSurf_SetupDepthAndCulling(void)
9394 // submodels are biased to avoid z-fighting with world surfaces that they
9395 // may be exactly overlapping (avoids z-fighting artifacts on certain
9396 // doors and things in Quake maps)
9397 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9398 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9399 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9400 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9403 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9405 // transparent sky would be ridiculous
9406 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9408 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9409 skyrenderlater = true;
9410 RSurf_SetupDepthAndCulling();
9412 // LordHavoc: HalfLife maps have freaky skypolys so don't use
9413 // skymasking on them, and Quake3 never did sky masking (unlike
9414 // software Quake and software Quake2), so disable the sky masking
9415 // in Quake3 maps as it causes problems with q3map2 sky tricks,
9416 // and skymasking also looks very bad when noclipping outside the
9417 // level, so don't use it then either.
9418 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9420 R_Mesh_ResetTextureState();
9421 if (skyrendermasked)
9423 R_SetupShader_DepthOrShadow();
9424 // depth-only (masking)
9425 GL_ColorMask(0,0,0,0);
9426 // just to make sure that braindead drivers don't draw
9427 // anything despite that colormask...
9428 GL_BlendFunc(GL_ZERO, GL_ONE);
9429 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9430 if (rsurface.batchvertex3fbuffer)
9431 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9433 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9437 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9439 GL_BlendFunc(GL_ONE, GL_ZERO);
9440 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9441 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9442 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9445 if (skyrendermasked)
9446 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9448 R_Mesh_ResetTextureState();
9449 GL_Color(1, 1, 1, 1);
9452 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9453 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9454 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9456 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9460 // render screenspace normalmap to texture
9462 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9467 // bind lightmap texture
9469 // water/refraction/reflection/camera surfaces have to be handled specially
9470 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9472 int start, end, startplaneindex;
9473 for (start = 0;start < texturenumsurfaces;start = end)
9475 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9476 if(startplaneindex < 0)
9478 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9479 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9483 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9485 // now that we have a batch using the same planeindex, render it
9486 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9488 // render water or distortion background
9490 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));
9492 // blend surface on top
9493 GL_DepthMask(false);
9494 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9497 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9499 // render surface with reflection texture as input
9500 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9501 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));
9508 // render surface batch normally
9509 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9510 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
9514 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9516 // OpenGL 1.3 path - anything not completely ancient
9517 qboolean applycolor;
9520 const texturelayer_t *layer;
9521 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);
9522 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9524 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9527 int layertexrgbscale;
9528 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9530 if (layerindex == 0)
9534 GL_AlphaTest(false);
9535 GL_DepthFunc(GL_EQUAL);
9538 GL_DepthMask(layer->depthmask && writedepth);
9539 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9540 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9542 layertexrgbscale = 4;
9543 VectorScale(layer->color, 0.25f, layercolor);
9545 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9547 layertexrgbscale = 2;
9548 VectorScale(layer->color, 0.5f, layercolor);
9552 layertexrgbscale = 1;
9553 VectorScale(layer->color, 1.0f, layercolor);
9555 layercolor[3] = layer->color[3];
9556 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9557 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9558 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9559 switch (layer->type)
9561 case TEXTURELAYERTYPE_LITTEXTURE:
9562 // single-pass lightmapped texture with 2x rgbscale
9563 R_Mesh_TexBind(0, r_texture_white);
9564 R_Mesh_TexMatrix(0, NULL);
9565 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9566 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9567 R_Mesh_TexBind(1, layer->texture);
9568 R_Mesh_TexMatrix(1, &layer->texmatrix);
9569 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9570 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9571 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9572 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9573 else if (FAKELIGHT_ENABLED)
9574 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9575 else if (rsurface.uselightmaptexture)
9576 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9578 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9580 case TEXTURELAYERTYPE_TEXTURE:
9581 // singletexture unlit texture with transparency support
9582 R_Mesh_TexBind(0, layer->texture);
9583 R_Mesh_TexMatrix(0, &layer->texmatrix);
9584 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9585 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9586 R_Mesh_TexBind(1, 0);
9587 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9588 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9590 case TEXTURELAYERTYPE_FOG:
9591 // singletexture fogging
9594 R_Mesh_TexBind(0, layer->texture);
9595 R_Mesh_TexMatrix(0, &layer->texmatrix);
9596 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9597 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9601 R_Mesh_TexBind(0, 0);
9602 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9604 R_Mesh_TexBind(1, 0);
9605 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9606 // generate a color array for the fog pass
9607 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9608 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9612 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9615 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9617 GL_DepthFunc(GL_LEQUAL);
9618 GL_AlphaTest(false);
9622 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9624 // OpenGL 1.1 - crusty old voodoo path
9627 const texturelayer_t *layer;
9628 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);
9629 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9631 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9633 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9635 if (layerindex == 0)
9639 GL_AlphaTest(false);
9640 GL_DepthFunc(GL_EQUAL);
9643 GL_DepthMask(layer->depthmask && writedepth);
9644 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9645 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9646 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9647 switch (layer->type)
9649 case TEXTURELAYERTYPE_LITTEXTURE:
9650 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9652 // two-pass lit texture with 2x rgbscale
9653 // first the lightmap pass
9654 R_Mesh_TexBind(0, r_texture_white);
9655 R_Mesh_TexMatrix(0, NULL);
9656 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9657 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9658 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9659 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9660 else if (FAKELIGHT_ENABLED)
9661 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9662 else if (rsurface.uselightmaptexture)
9663 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9665 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9666 // then apply the texture to it
9667 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9668 R_Mesh_TexBind(0, layer->texture);
9669 R_Mesh_TexMatrix(0, &layer->texmatrix);
9670 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9671 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9672 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);
9676 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9677 R_Mesh_TexBind(0, layer->texture);
9678 R_Mesh_TexMatrix(0, &layer->texmatrix);
9679 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9680 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9681 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9682 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);
9684 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);
9687 case TEXTURELAYERTYPE_TEXTURE:
9688 // singletexture unlit texture with transparency support
9689 R_Mesh_TexBind(0, layer->texture);
9690 R_Mesh_TexMatrix(0, &layer->texmatrix);
9691 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9692 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9693 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);
9695 case TEXTURELAYERTYPE_FOG:
9696 // singletexture fogging
9699 R_Mesh_TexBind(0, layer->texture);
9700 R_Mesh_TexMatrix(0, &layer->texmatrix);
9701 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9702 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9706 R_Mesh_TexBind(0, 0);
9707 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9709 // generate a color array for the fog pass
9710 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9711 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9715 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9718 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9720 GL_DepthFunc(GL_LEQUAL);
9721 GL_AlphaTest(false);
9725 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9729 r_vertexgeneric_t *batchvertex;
9732 // R_Mesh_ResetTextureState();
9733 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9735 if(rsurface.texture && rsurface.texture->currentskinframe)
9737 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9738 c[3] *= rsurface.texture->currentalpha;
9748 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9750 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9751 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9752 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9755 // brighten it up (as texture value 127 means "unlit")
9756 c[0] *= 2 * r_refdef.view.colorscale;
9757 c[1] *= 2 * r_refdef.view.colorscale;
9758 c[2] *= 2 * r_refdef.view.colorscale;
9760 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9761 c[3] *= r_wateralpha.value;
9763 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9765 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9766 GL_DepthMask(false);
9768 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9770 GL_BlendFunc(GL_ONE, GL_ONE);
9771 GL_DepthMask(false);
9773 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9775 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9776 GL_DepthMask(false);
9778 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9780 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9781 GL_DepthMask(false);
9785 GL_BlendFunc(GL_ONE, GL_ZERO);
9786 GL_DepthMask(writedepth);
9789 if (r_showsurfaces.integer == 3)
9791 rsurface.passcolor4f = NULL;
9793 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9795 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9797 rsurface.passcolor4f = NULL;
9798 rsurface.passcolor4f_vertexbuffer = 0;
9799 rsurface.passcolor4f_bufferoffset = 0;
9801 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9803 qboolean applycolor = true;
9806 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9808 r_refdef.lightmapintensity = 1;
9809 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9810 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9812 else if (FAKELIGHT_ENABLED)
9814 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9816 r_refdef.lightmapintensity = r_fakelight_intensity.value;
9817 RSurf_DrawBatch_GL11_ApplyFakeLight();
9818 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9822 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9824 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9825 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9826 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9829 if(!rsurface.passcolor4f)
9830 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9832 RSurf_DrawBatch_GL11_ApplyAmbient();
9833 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9834 if(r_refdef.fogenabled)
9835 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9836 RSurf_DrawBatch_GL11_ClampColor();
9838 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9839 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9842 else if (!r_refdef.view.showdebug)
9844 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9845 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9846 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9848 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9849 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9851 R_Mesh_PrepareVertices_Generic_Unlock();
9854 else if (r_showsurfaces.integer == 4)
9856 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9857 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9858 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9860 unsigned char c = (vi << 3) * (1.0f / 256.0f);
9861 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9862 Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9864 R_Mesh_PrepareVertices_Generic_Unlock();
9867 else if (r_showsurfaces.integer == 2)
9870 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9871 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9872 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9874 unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9875 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9876 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9877 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9878 Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9879 Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9880 Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9882 R_Mesh_PrepareVertices_Generic_Unlock();
9883 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9887 int texturesurfaceindex;
9889 const msurface_t *surface;
9890 float surfacecolor4f[4];
9891 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9892 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9894 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9896 surface = texturesurfacelist[texturesurfaceindex];
9897 k = (int)(((size_t)surface) / sizeof(msurface_t));
9898 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9899 for (j = 0;j < surface->num_vertices;j++)
9901 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9902 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
9906 R_Mesh_PrepareVertices_Generic_Unlock();
9911 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9914 RSurf_SetupDepthAndCulling();
9915 if (r_showsurfaces.integer)
9917 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9920 switch (vid.renderpath)
9922 case RENDERPATH_GL20:
9923 case RENDERPATH_D3D9:
9924 case RENDERPATH_D3D10:
9925 case RENDERPATH_D3D11:
9926 case RENDERPATH_SOFT:
9927 case RENDERPATH_GLES2:
9928 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9930 case RENDERPATH_GL13:
9931 case RENDERPATH_GLES1:
9932 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9934 case RENDERPATH_GL11:
9935 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9941 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9944 RSurf_SetupDepthAndCulling();
9945 if (r_showsurfaces.integer)
9947 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9950 switch (vid.renderpath)
9952 case RENDERPATH_GL20:
9953 case RENDERPATH_D3D9:
9954 case RENDERPATH_D3D10:
9955 case RENDERPATH_D3D11:
9956 case RENDERPATH_SOFT:
9957 case RENDERPATH_GLES2:
9958 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9960 case RENDERPATH_GL13:
9961 case RENDERPATH_GLES1:
9962 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9964 case RENDERPATH_GL11:
9965 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9971 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9974 int texturenumsurfaces, endsurface;
9976 const msurface_t *surface;
9977 const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
9979 // if the model is static it doesn't matter what value we give for
9980 // wantnormals and wanttangents, so this logic uses only rules applicable
9981 // to a model, knowing that they are meaningless otherwise
9982 if (ent == r_refdef.scene.worldentity)
9983 RSurf_ActiveWorldEntity();
9984 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9985 RSurf_ActiveModelEntity(ent, false, false, false);
9988 switch (vid.renderpath)
9990 case RENDERPATH_GL20:
9991 case RENDERPATH_D3D9:
9992 case RENDERPATH_D3D10:
9993 case RENDERPATH_D3D11:
9994 case RENDERPATH_SOFT:
9995 case RENDERPATH_GLES2:
9996 RSurf_ActiveModelEntity(ent, true, true, false);
9998 case RENDERPATH_GL11:
9999 case RENDERPATH_GL13:
10000 case RENDERPATH_GLES1:
10001 RSurf_ActiveModelEntity(ent, true, false, false);
10006 if (r_transparentdepthmasking.integer)
10008 qboolean setup = false;
10009 for (i = 0;i < numsurfaces;i = j)
10012 surface = rsurface.modelsurfaces + surfacelist[i];
10013 texture = surface->texture;
10014 rsurface.texture = R_GetCurrentTexture(texture);
10015 rsurface.lightmaptexture = NULL;
10016 rsurface.deluxemaptexture = NULL;
10017 rsurface.uselightmaptexture = false;
10018 // scan ahead until we find a different texture
10019 endsurface = min(i + 1024, numsurfaces);
10020 texturenumsurfaces = 0;
10021 texturesurfacelist[texturenumsurfaces++] = surface;
10022 for (;j < endsurface;j++)
10024 surface = rsurface.modelsurfaces + surfacelist[j];
10025 if (texture != surface->texture)
10027 texturesurfacelist[texturenumsurfaces++] = surface;
10029 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10031 // render the range of surfaces as depth
10035 GL_ColorMask(0,0,0,0);
10037 GL_DepthTest(true);
10038 GL_BlendFunc(GL_ONE, GL_ZERO);
10039 GL_DepthMask(true);
10040 // R_Mesh_ResetTextureState();
10041 R_SetupShader_DepthOrShadow();
10043 RSurf_SetupDepthAndCulling();
10044 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10045 if (rsurface.batchvertex3fbuffer)
10046 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10048 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10052 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10055 for (i = 0;i < numsurfaces;i = j)
10058 surface = rsurface.modelsurfaces + surfacelist[i];
10059 texture = surface->texture;
10060 rsurface.texture = R_GetCurrentTexture(texture);
10061 // scan ahead until we find a different texture
10062 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10063 texturenumsurfaces = 0;
10064 texturesurfacelist[texturenumsurfaces++] = surface;
10065 if(FAKELIGHT_ENABLED)
10067 rsurface.lightmaptexture = NULL;
10068 rsurface.deluxemaptexture = NULL;
10069 rsurface.uselightmaptexture = false;
10070 for (;j < endsurface;j++)
10072 surface = rsurface.modelsurfaces + surfacelist[j];
10073 if (texture != surface->texture)
10075 texturesurfacelist[texturenumsurfaces++] = surface;
10080 rsurface.lightmaptexture = surface->lightmaptexture;
10081 rsurface.deluxemaptexture = surface->deluxemaptexture;
10082 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10083 for (;j < endsurface;j++)
10085 surface = rsurface.modelsurfaces + surfacelist[j];
10086 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10088 texturesurfacelist[texturenumsurfaces++] = surface;
10091 // render the range of surfaces
10092 if (ent == r_refdef.scene.worldentity)
10093 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10095 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10097 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10100 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10102 // transparent surfaces get pushed off into the transparent queue
10103 int surfacelistindex;
10104 const msurface_t *surface;
10105 vec3_t tempcenter, center;
10106 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10108 surface = texturesurfacelist[surfacelistindex];
10109 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10110 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10111 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10112 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10113 if (queueentity->transparent_offset) // transparent offset
10115 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10116 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10117 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10119 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10123 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10125 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10127 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10129 RSurf_SetupDepthAndCulling();
10130 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10131 if (rsurface.batchvertex3fbuffer)
10132 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10134 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10138 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10140 const entity_render_t *queueentity = r_refdef.scene.worldentity;
10143 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10146 if (!rsurface.texture->currentnumlayers)
10148 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10149 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10151 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10153 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10154 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10155 else if (!rsurface.texture->currentnumlayers)
10157 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10159 // in the deferred case, transparent surfaces were queued during prepass
10160 if (!r_shadow_usingdeferredprepass)
10161 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10165 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10166 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10171 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10174 texture_t *texture;
10175 R_FrameData_SetMark();
10176 // break the surface list down into batches by texture and use of lightmapping
10177 for (i = 0;i < numsurfaces;i = j)
10180 // texture is the base texture pointer, rsurface.texture is the
10181 // current frame/skin the texture is directing us to use (for example
10182 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10183 // use skin 1 instead)
10184 texture = surfacelist[i]->texture;
10185 rsurface.texture = R_GetCurrentTexture(texture);
10186 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10188 // if this texture is not the kind we want, skip ahead to the next one
10189 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10193 if(FAKELIGHT_ENABLED || depthonly || prepass)
10195 rsurface.lightmaptexture = NULL;
10196 rsurface.deluxemaptexture = NULL;
10197 rsurface.uselightmaptexture = false;
10198 // simply scan ahead until we find a different texture or lightmap state
10199 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10204 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10205 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10206 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10207 // simply scan ahead until we find a different texture or lightmap state
10208 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10211 // render the range of surfaces
10212 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10214 R_FrameData_ReturnToMark();
10217 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10221 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10224 if (!rsurface.texture->currentnumlayers)
10226 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10227 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10229 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10231 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10232 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10233 else if (!rsurface.texture->currentnumlayers)
10235 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10237 // in the deferred case, transparent surfaces were queued during prepass
10238 if (!r_shadow_usingdeferredprepass)
10239 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10243 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10244 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10249 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10252 texture_t *texture;
10253 R_FrameData_SetMark();
10254 // break the surface list down into batches by texture and use of lightmapping
10255 for (i = 0;i < numsurfaces;i = j)
10258 // texture is the base texture pointer, rsurface.texture is the
10259 // current frame/skin the texture is directing us to use (for example
10260 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10261 // use skin 1 instead)
10262 texture = surfacelist[i]->texture;
10263 rsurface.texture = R_GetCurrentTexture(texture);
10264 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10266 // if this texture is not the kind we want, skip ahead to the next one
10267 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10271 if(FAKELIGHT_ENABLED || depthonly || prepass)
10273 rsurface.lightmaptexture = NULL;
10274 rsurface.deluxemaptexture = NULL;
10275 rsurface.uselightmaptexture = false;
10276 // simply scan ahead until we find a different texture or lightmap state
10277 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10282 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10283 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10284 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10285 // simply scan ahead until we find a different texture or lightmap state
10286 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10289 // render the range of surfaces
10290 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10292 R_FrameData_ReturnToMark();
10295 float locboxvertex3f[6*4*3] =
10297 1,0,1, 1,0,0, 1,1,0, 1,1,1,
10298 0,1,1, 0,1,0, 0,0,0, 0,0,1,
10299 1,1,1, 1,1,0, 0,1,0, 0,1,1,
10300 0,0,1, 0,0,0, 1,0,0, 1,0,1,
10301 0,0,1, 1,0,1, 1,1,1, 0,1,1,
10302 1,0,0, 0,0,0, 0,1,0, 1,1,0
10305 unsigned short locboxelements[6*2*3] =
10310 12,13,14, 12,14,15,
10311 16,17,18, 16,18,19,
10315 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10318 cl_locnode_t *loc = (cl_locnode_t *)ent;
10320 float vertex3f[6*4*3];
10322 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10323 GL_DepthMask(false);
10324 GL_DepthRange(0, 1);
10325 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10326 GL_DepthTest(true);
10327 GL_CullFace(GL_NONE);
10328 R_EntityMatrix(&identitymatrix);
10330 // R_Mesh_ResetTextureState();
10332 i = surfacelist[0];
10333 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10334 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10335 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10336 surfacelist[0] < 0 ? 0.5f : 0.125f);
10338 if (VectorCompare(loc->mins, loc->maxs))
10340 VectorSet(size, 2, 2, 2);
10341 VectorMA(loc->mins, -0.5f, size, mins);
10345 VectorCopy(loc->mins, mins);
10346 VectorSubtract(loc->maxs, loc->mins, size);
10349 for (i = 0;i < 6*4*3;)
10350 for (j = 0;j < 3;j++, i++)
10351 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10353 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10354 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10355 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10358 void R_DrawLocs(void)
10361 cl_locnode_t *loc, *nearestloc;
10363 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10364 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10366 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10367 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10371 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10373 if (decalsystem->decals)
10374 Mem_Free(decalsystem->decals);
10375 memset(decalsystem, 0, sizeof(*decalsystem));
10378 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)
10381 tridecal_t *decals;
10384 // expand or initialize the system
10385 if (decalsystem->maxdecals <= decalsystem->numdecals)
10387 decalsystem_t old = *decalsystem;
10388 qboolean useshortelements;
10389 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10390 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10391 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)));
10392 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10393 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10394 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10395 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10396 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10397 if (decalsystem->numdecals)
10398 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10400 Mem_Free(old.decals);
10401 for (i = 0;i < decalsystem->maxdecals*3;i++)
10402 decalsystem->element3i[i] = i;
10403 if (useshortelements)
10404 for (i = 0;i < decalsystem->maxdecals*3;i++)
10405 decalsystem->element3s[i] = i;
10408 // grab a decal and search for another free slot for the next one
10409 decals = decalsystem->decals;
10410 decal = decalsystem->decals + (i = decalsystem->freedecal++);
10411 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10413 decalsystem->freedecal = i;
10414 if (decalsystem->numdecals <= i)
10415 decalsystem->numdecals = i + 1;
10417 // initialize the decal
10419 decal->triangleindex = triangleindex;
10420 decal->surfaceindex = surfaceindex;
10421 decal->decalsequence = decalsequence;
10422 decal->color4f[0][0] = c0[0];
10423 decal->color4f[0][1] = c0[1];
10424 decal->color4f[0][2] = c0[2];
10425 decal->color4f[0][3] = 1;
10426 decal->color4f[1][0] = c1[0];
10427 decal->color4f[1][1] = c1[1];
10428 decal->color4f[1][2] = c1[2];
10429 decal->color4f[1][3] = 1;
10430 decal->color4f[2][0] = c2[0];
10431 decal->color4f[2][1] = c2[1];
10432 decal->color4f[2][2] = c2[2];
10433 decal->color4f[2][3] = 1;
10434 decal->vertex3f[0][0] = v0[0];
10435 decal->vertex3f[0][1] = v0[1];
10436 decal->vertex3f[0][2] = v0[2];
10437 decal->vertex3f[1][0] = v1[0];
10438 decal->vertex3f[1][1] = v1[1];
10439 decal->vertex3f[1][2] = v1[2];
10440 decal->vertex3f[2][0] = v2[0];
10441 decal->vertex3f[2][1] = v2[1];
10442 decal->vertex3f[2][2] = v2[2];
10443 decal->texcoord2f[0][0] = t0[0];
10444 decal->texcoord2f[0][1] = t0[1];
10445 decal->texcoord2f[1][0] = t1[0];
10446 decal->texcoord2f[1][1] = t1[1];
10447 decal->texcoord2f[2][0] = t2[0];
10448 decal->texcoord2f[2][1] = t2[1];
10449 TriangleNormal(v0, v1, v2, decal->plane);
10450 VectorNormalize(decal->plane);
10451 decal->plane[3] = DotProduct(v0, decal->plane);
10454 extern cvar_t cl_decals_bias;
10455 extern cvar_t cl_decals_models;
10456 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10457 // baseparms, parms, temps
10458 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)
10463 const float *vertex3f;
10464 const float *normal3f;
10466 float points[2][9][3];
10473 e = rsurface.modelelement3i + 3*triangleindex;
10475 vertex3f = rsurface.modelvertex3f;
10476 normal3f = rsurface.modelnormal3f;
10480 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10482 index = 3*e[cornerindex];
10483 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10488 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10490 index = 3*e[cornerindex];
10491 VectorCopy(vertex3f + index, v[cornerindex]);
10496 //TriangleNormal(v[0], v[1], v[2], normal);
10497 //if (DotProduct(normal, localnormal) < 0.0f)
10499 // clip by each of the box planes formed from the projection matrix
10500 // if anything survives, we emit the decal
10501 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]);
10504 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]);
10507 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]);
10510 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]);
10513 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]);
10516 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]);
10519 // some part of the triangle survived, so we have to accept it...
10522 // dynamic always uses the original triangle
10524 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10526 index = 3*e[cornerindex];
10527 VectorCopy(vertex3f + index, v[cornerindex]);
10530 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10532 // convert vertex positions to texcoords
10533 Matrix4x4_Transform(projection, v[cornerindex], temp);
10534 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10535 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10536 // calculate distance fade from the projection origin
10537 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10538 f = bound(0.0f, f, 1.0f);
10539 c[cornerindex][0] = r * f;
10540 c[cornerindex][1] = g * f;
10541 c[cornerindex][2] = b * f;
10542 c[cornerindex][3] = 1.0f;
10543 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10546 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);
10548 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10549 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);
10551 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)
10553 matrix4x4_t projection;
10554 decalsystem_t *decalsystem;
10557 const msurface_t *surface;
10558 const msurface_t *surfaces;
10559 const int *surfacelist;
10560 const texture_t *texture;
10562 int numsurfacelist;
10563 int surfacelistindex;
10566 float localorigin[3];
10567 float localnormal[3];
10568 float localmins[3];
10569 float localmaxs[3];
10572 float planes[6][4];
10575 int bih_triangles_count;
10576 int bih_triangles[256];
10577 int bih_surfaces[256];
10579 decalsystem = &ent->decalsystem;
10580 model = ent->model;
10581 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10583 R_DecalSystem_Reset(&ent->decalsystem);
10587 if (!model->brush.data_leafs && !cl_decals_models.integer)
10589 if (decalsystem->model)
10590 R_DecalSystem_Reset(decalsystem);
10594 if (decalsystem->model != model)
10595 R_DecalSystem_Reset(decalsystem);
10596 decalsystem->model = model;
10598 RSurf_ActiveModelEntity(ent, true, false, false);
10600 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10601 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10602 VectorNormalize(localnormal);
10603 localsize = worldsize*rsurface.inversematrixscale;
10604 localmins[0] = localorigin[0] - localsize;
10605 localmins[1] = localorigin[1] - localsize;
10606 localmins[2] = localorigin[2] - localsize;
10607 localmaxs[0] = localorigin[0] + localsize;
10608 localmaxs[1] = localorigin[1] + localsize;
10609 localmaxs[2] = localorigin[2] + localsize;
10611 //VectorCopy(localnormal, planes[4]);
10612 //VectorVectors(planes[4], planes[2], planes[0]);
10613 AnglesFromVectors(angles, localnormal, NULL, false);
10614 AngleVectors(angles, planes[0], planes[2], planes[4]);
10615 VectorNegate(planes[0], planes[1]);
10616 VectorNegate(planes[2], planes[3]);
10617 VectorNegate(planes[4], planes[5]);
10618 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10619 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10620 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10621 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10622 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10623 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10628 matrix4x4_t forwardprojection;
10629 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10630 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10635 float projectionvector[4][3];
10636 VectorScale(planes[0], ilocalsize, projectionvector[0]);
10637 VectorScale(planes[2], ilocalsize, projectionvector[1]);
10638 VectorScale(planes[4], ilocalsize, projectionvector[2]);
10639 projectionvector[0][0] = planes[0][0] * ilocalsize;
10640 projectionvector[0][1] = planes[1][0] * ilocalsize;
10641 projectionvector[0][2] = planes[2][0] * ilocalsize;
10642 projectionvector[1][0] = planes[0][1] * ilocalsize;
10643 projectionvector[1][1] = planes[1][1] * ilocalsize;
10644 projectionvector[1][2] = planes[2][1] * ilocalsize;
10645 projectionvector[2][0] = planes[0][2] * ilocalsize;
10646 projectionvector[2][1] = planes[1][2] * ilocalsize;
10647 projectionvector[2][2] = planes[2][2] * ilocalsize;
10648 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10649 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10650 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10651 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10655 dynamic = model->surfmesh.isanimated;
10656 numsurfacelist = model->nummodelsurfaces;
10657 surfacelist = model->sortedmodelsurfaces;
10658 surfaces = model->data_surfaces;
10661 bih_triangles_count = -1;
10664 if(model->render_bih.numleafs)
10665 bih = &model->render_bih;
10666 else if(model->collision_bih.numleafs)
10667 bih = &model->collision_bih;
10670 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10671 if(bih_triangles_count == 0)
10673 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10675 if(bih_triangles_count > 0)
10677 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10679 surfaceindex = bih_surfaces[triangleindex];
10680 surface = surfaces + surfaceindex;
10681 texture = surface->texture;
10682 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10684 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10686 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10691 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10693 surfaceindex = surfacelist[surfacelistindex];
10694 surface = surfaces + surfaceindex;
10695 // check cull box first because it rejects more than any other check
10696 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10698 // skip transparent surfaces
10699 texture = surface->texture;
10700 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10702 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10704 numtriangles = surface->num_triangles;
10705 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10706 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10711 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10712 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)
10714 int renderentityindex;
10715 float worldmins[3];
10716 float worldmaxs[3];
10717 entity_render_t *ent;
10719 if (!cl_decals_newsystem.integer)
10722 worldmins[0] = worldorigin[0] - worldsize;
10723 worldmins[1] = worldorigin[1] - worldsize;
10724 worldmins[2] = worldorigin[2] - worldsize;
10725 worldmaxs[0] = worldorigin[0] + worldsize;
10726 worldmaxs[1] = worldorigin[1] + worldsize;
10727 worldmaxs[2] = worldorigin[2] + worldsize;
10729 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10731 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10733 ent = r_refdef.scene.entities[renderentityindex];
10734 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10737 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10741 typedef struct r_decalsystem_splatqueue_s
10743 vec3_t worldorigin;
10744 vec3_t worldnormal;
10750 r_decalsystem_splatqueue_t;
10752 int r_decalsystem_numqueued = 0;
10753 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10755 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)
10757 r_decalsystem_splatqueue_t *queue;
10759 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10762 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10763 VectorCopy(worldorigin, queue->worldorigin);
10764 VectorCopy(worldnormal, queue->worldnormal);
10765 Vector4Set(queue->color, r, g, b, a);
10766 Vector4Set(queue->tcrange, s1, t1, s2, t2);
10767 queue->worldsize = worldsize;
10768 queue->decalsequence = cl.decalsequence++;
10771 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10774 r_decalsystem_splatqueue_t *queue;
10776 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10777 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);
10778 r_decalsystem_numqueued = 0;
10781 extern cvar_t cl_decals_max;
10782 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10785 decalsystem_t *decalsystem = &ent->decalsystem;
10792 if (!decalsystem->numdecals)
10795 if (r_showsurfaces.integer)
10798 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10800 R_DecalSystem_Reset(decalsystem);
10804 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10805 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10807 if (decalsystem->lastupdatetime)
10808 frametime = (cl.time - decalsystem->lastupdatetime);
10811 decalsystem->lastupdatetime = cl.time;
10812 decal = decalsystem->decals;
10813 numdecals = decalsystem->numdecals;
10815 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10817 if (decal->color4f[0][3])
10819 decal->lived += frametime;
10820 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10822 memset(decal, 0, sizeof(*decal));
10823 if (decalsystem->freedecal > i)
10824 decalsystem->freedecal = i;
10828 decal = decalsystem->decals;
10829 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10832 // collapse the array by shuffling the tail decals into the gaps
10835 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10836 decalsystem->freedecal++;
10837 if (decalsystem->freedecal == numdecals)
10839 decal[decalsystem->freedecal] = decal[--numdecals];
10842 decalsystem->numdecals = numdecals;
10844 if (numdecals <= 0)
10846 // if there are no decals left, reset decalsystem
10847 R_DecalSystem_Reset(decalsystem);
10851 extern skinframe_t *decalskinframe;
10852 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10855 decalsystem_t *decalsystem = &ent->decalsystem;
10864 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10867 numdecals = decalsystem->numdecals;
10871 if (r_showsurfaces.integer)
10874 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10876 R_DecalSystem_Reset(decalsystem);
10880 // if the model is static it doesn't matter what value we give for
10881 // wantnormals and wanttangents, so this logic uses only rules applicable
10882 // to a model, knowing that they are meaningless otherwise
10883 if (ent == r_refdef.scene.worldentity)
10884 RSurf_ActiveWorldEntity();
10886 RSurf_ActiveModelEntity(ent, false, false, false);
10888 decalsystem->lastupdatetime = cl.time;
10889 decal = decalsystem->decals;
10891 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10893 // update vertex positions for animated models
10894 v3f = decalsystem->vertex3f;
10895 c4f = decalsystem->color4f;
10896 t2f = decalsystem->texcoord2f;
10897 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10899 if (!decal->color4f[0][3])
10902 if (surfacevisible && !surfacevisible[decal->surfaceindex])
10906 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
10909 // update color values for fading decals
10910 if (decal->lived >= cl_decals_time.value)
10911 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
10915 c4f[ 0] = decal->color4f[0][0] * alpha;
10916 c4f[ 1] = decal->color4f[0][1] * alpha;
10917 c4f[ 2] = decal->color4f[0][2] * alpha;
10919 c4f[ 4] = decal->color4f[1][0] * alpha;
10920 c4f[ 5] = decal->color4f[1][1] * alpha;
10921 c4f[ 6] = decal->color4f[1][2] * alpha;
10923 c4f[ 8] = decal->color4f[2][0] * alpha;
10924 c4f[ 9] = decal->color4f[2][1] * alpha;
10925 c4f[10] = decal->color4f[2][2] * alpha;
10928 t2f[0] = decal->texcoord2f[0][0];
10929 t2f[1] = decal->texcoord2f[0][1];
10930 t2f[2] = decal->texcoord2f[1][0];
10931 t2f[3] = decal->texcoord2f[1][1];
10932 t2f[4] = decal->texcoord2f[2][0];
10933 t2f[5] = decal->texcoord2f[2][1];
10935 // update vertex positions for animated models
10936 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
10938 e = rsurface.modelelement3i + 3*decal->triangleindex;
10939 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
10940 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
10941 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
10945 VectorCopy(decal->vertex3f[0], v3f);
10946 VectorCopy(decal->vertex3f[1], v3f + 3);
10947 VectorCopy(decal->vertex3f[2], v3f + 6);
10950 if (r_refdef.fogenabled)
10952 alpha = RSurf_FogVertex(v3f);
10953 VectorScale(c4f, alpha, c4f);
10954 alpha = RSurf_FogVertex(v3f + 3);
10955 VectorScale(c4f + 4, alpha, c4f + 4);
10956 alpha = RSurf_FogVertex(v3f + 6);
10957 VectorScale(c4f + 8, alpha, c4f + 8);
10968 r_refdef.stats.drawndecals += numtris;
10970 // now render the decals all at once
10971 // (this assumes they all use one particle font texture!)
10972 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);
10973 // R_Mesh_ResetTextureState();
10974 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
10975 GL_DepthMask(false);
10976 GL_DepthRange(0, 1);
10977 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
10978 GL_DepthTest(true);
10979 GL_CullFace(GL_NONE);
10980 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
10981 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
10982 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
10986 static void R_DrawModelDecals(void)
10990 // fade faster when there are too many decals
10991 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10992 for (i = 0;i < r_refdef.scene.numentities;i++)
10993 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10995 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
10996 for (i = 0;i < r_refdef.scene.numentities;i++)
10997 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10998 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11000 R_DecalSystem_ApplySplatEntitiesQueue();
11002 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11003 for (i = 0;i < r_refdef.scene.numentities;i++)
11004 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11006 r_refdef.stats.totaldecals += numdecals;
11008 if (r_showsurfaces.integer)
11011 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11013 for (i = 0;i < r_refdef.scene.numentities;i++)
11015 if (!r_refdef.viewcache.entityvisible[i])
11017 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11018 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11022 extern cvar_t mod_collision_bih;
11023 void R_DrawDebugModel(void)
11025 entity_render_t *ent = rsurface.entity;
11026 int i, j, k, l, flagsmask;
11027 const msurface_t *surface;
11028 dp_model_t *model = ent->model;
11031 if (!sv.active && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11034 if (r_showoverdraw.value > 0)
11036 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11037 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11038 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11039 GL_DepthTest(false);
11040 GL_DepthMask(false);
11041 GL_DepthRange(0, 1);
11042 GL_BlendFunc(GL_ONE, GL_ONE);
11043 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11045 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11047 rsurface.texture = R_GetCurrentTexture(surface->texture);
11048 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11050 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11051 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11052 if (!rsurface.texture->currentlayers->depthmask)
11053 GL_Color(c, 0, 0, 1.0f);
11054 else if (ent == r_refdef.scene.worldentity)
11055 GL_Color(c, c, c, 1.0f);
11057 GL_Color(0, c, 0, 1.0f);
11058 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11062 rsurface.texture = NULL;
11065 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11067 // R_Mesh_ResetTextureState();
11068 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11069 GL_DepthRange(0, 1);
11070 GL_DepthTest(!r_showdisabledepthtest.integer);
11071 GL_DepthMask(false);
11072 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11074 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11078 qboolean cullbox = ent == r_refdef.scene.worldentity;
11079 const q3mbrush_t *brush;
11080 const bih_t *bih = &model->collision_bih;
11081 const bih_leaf_t *bihleaf;
11082 float vertex3f[3][3];
11083 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11085 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11087 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11089 switch (bihleaf->type)
11092 brush = model->brush.data_brushes + bihleaf->itemindex;
11093 if (brush->colbrushf && brush->colbrushf->numtriangles)
11095 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);
11096 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11097 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11100 case BIH_COLLISIONTRIANGLE:
11101 triangleindex = bihleaf->itemindex;
11102 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11103 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11104 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11105 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);
11106 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11107 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11109 case BIH_RENDERTRIANGLE:
11110 triangleindex = bihleaf->itemindex;
11111 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11112 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11113 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11114 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);
11115 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11116 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11122 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11124 if (r_showtris.integer && qglPolygonMode)
11126 if (r_showdisabledepthtest.integer)
11128 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11129 GL_DepthMask(false);
11133 GL_BlendFunc(GL_ONE, GL_ZERO);
11134 GL_DepthMask(true);
11136 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11137 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11139 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11141 rsurface.texture = R_GetCurrentTexture(surface->texture);
11142 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11144 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11145 if (!rsurface.texture->currentlayers->depthmask)
11146 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11147 else if (ent == r_refdef.scene.worldentity)
11148 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11150 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11151 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11155 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11156 rsurface.texture = NULL;
11159 if (r_shownormals.value != 0 && qglBegin)
11161 if (r_showdisabledepthtest.integer)
11163 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11164 GL_DepthMask(false);
11168 GL_BlendFunc(GL_ONE, GL_ZERO);
11169 GL_DepthMask(true);
11171 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11173 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11175 rsurface.texture = R_GetCurrentTexture(surface->texture);
11176 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11178 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11179 qglBegin(GL_LINES);
11180 if (r_shownormals.value < 0)
11182 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11184 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11185 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11186 qglVertex3f(v[0], v[1], v[2]);
11187 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11188 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11189 qglVertex3f(v[0], v[1], v[2]);
11192 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11194 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11196 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11197 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11198 qglVertex3f(v[0], v[1], v[2]);
11199 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11200 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11201 qglVertex3f(v[0], v[1], v[2]);
11203 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11205 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11206 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11207 qglVertex3f(v[0], v[1], v[2]);
11208 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11209 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11210 qglVertex3f(v[0], v[1], v[2]);
11212 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11214 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11215 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11216 qglVertex3f(v[0], v[1], v[2]);
11217 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11218 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11219 qglVertex3f(v[0], v[1], v[2]);
11226 rsurface.texture = NULL;
11230 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11231 int r_maxsurfacelist = 0;
11232 const msurface_t **r_surfacelist = NULL;
11233 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11235 int i, j, endj, flagsmask;
11236 dp_model_t *model = r_refdef.scene.worldmodel;
11237 msurface_t *surfaces;
11238 unsigned char *update;
11239 int numsurfacelist = 0;
11243 if (r_maxsurfacelist < model->num_surfaces)
11245 r_maxsurfacelist = model->num_surfaces;
11247 Mem_Free((msurface_t**)r_surfacelist);
11248 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11251 RSurf_ActiveWorldEntity();
11253 surfaces = model->data_surfaces;
11254 update = model->brushq1.lightmapupdateflags;
11256 // update light styles on this submodel
11257 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11259 model_brush_lightstyleinfo_t *style;
11260 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11262 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11264 int *list = style->surfacelist;
11265 style->value = r_refdef.scene.lightstylevalue[style->style];
11266 for (j = 0;j < style->numsurfaces;j++)
11267 update[list[j]] = true;
11272 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11276 R_DrawDebugModel();
11277 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11281 rsurface.lightmaptexture = NULL;
11282 rsurface.deluxemaptexture = NULL;
11283 rsurface.uselightmaptexture = false;
11284 rsurface.texture = NULL;
11285 rsurface.rtlight = NULL;
11286 numsurfacelist = 0;
11287 // add visible surfaces to draw list
11288 for (i = 0;i < model->nummodelsurfaces;i++)
11290 j = model->sortedmodelsurfaces[i];
11291 if (r_refdef.viewcache.world_surfacevisible[j])
11292 r_surfacelist[numsurfacelist++] = surfaces + j;
11294 // update lightmaps if needed
11295 if (model->brushq1.firstrender)
11297 model->brushq1.firstrender = false;
11298 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11300 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11304 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11305 if (r_refdef.viewcache.world_surfacevisible[j])
11307 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11309 // don't do anything if there were no surfaces
11310 if (!numsurfacelist)
11312 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11315 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11317 // add to stats if desired
11318 if (r_speeds.integer && !skysurfaces && !depthonly)
11320 r_refdef.stats.world_surfaces += numsurfacelist;
11321 for (j = 0;j < numsurfacelist;j++)
11322 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11325 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11328 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11330 int i, j, endj, flagsmask;
11331 dp_model_t *model = ent->model;
11332 msurface_t *surfaces;
11333 unsigned char *update;
11334 int numsurfacelist = 0;
11338 if (r_maxsurfacelist < model->num_surfaces)
11340 r_maxsurfacelist = model->num_surfaces;
11342 Mem_Free((msurface_t **)r_surfacelist);
11343 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11346 // if the model is static it doesn't matter what value we give for
11347 // wantnormals and wanttangents, so this logic uses only rules applicable
11348 // to a model, knowing that they are meaningless otherwise
11349 if (ent == r_refdef.scene.worldentity)
11350 RSurf_ActiveWorldEntity();
11351 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11352 RSurf_ActiveModelEntity(ent, false, false, false);
11354 RSurf_ActiveModelEntity(ent, true, true, true);
11355 else if (depthonly)
11357 switch (vid.renderpath)
11359 case RENDERPATH_GL20:
11360 case RENDERPATH_D3D9:
11361 case RENDERPATH_D3D10:
11362 case RENDERPATH_D3D11:
11363 case RENDERPATH_SOFT:
11364 case RENDERPATH_GLES2:
11365 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11367 case RENDERPATH_GL11:
11368 case RENDERPATH_GL13:
11369 case RENDERPATH_GLES1:
11370 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11376 switch (vid.renderpath)
11378 case RENDERPATH_GL20:
11379 case RENDERPATH_D3D9:
11380 case RENDERPATH_D3D10:
11381 case RENDERPATH_D3D11:
11382 case RENDERPATH_SOFT:
11383 case RENDERPATH_GLES2:
11384 RSurf_ActiveModelEntity(ent, true, true, false);
11386 case RENDERPATH_GL11:
11387 case RENDERPATH_GL13:
11388 case RENDERPATH_GLES1:
11389 RSurf_ActiveModelEntity(ent, true, false, false);
11394 surfaces = model->data_surfaces;
11395 update = model->brushq1.lightmapupdateflags;
11397 // update light styles
11398 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11400 model_brush_lightstyleinfo_t *style;
11401 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11403 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11405 int *list = style->surfacelist;
11406 style->value = r_refdef.scene.lightstylevalue[style->style];
11407 for (j = 0;j < style->numsurfaces;j++)
11408 update[list[j]] = true;
11413 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11417 R_DrawDebugModel();
11418 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11422 rsurface.lightmaptexture = NULL;
11423 rsurface.deluxemaptexture = NULL;
11424 rsurface.uselightmaptexture = false;
11425 rsurface.texture = NULL;
11426 rsurface.rtlight = NULL;
11427 numsurfacelist = 0;
11428 // add visible surfaces to draw list
11429 for (i = 0;i < model->nummodelsurfaces;i++)
11430 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11431 // don't do anything if there were no surfaces
11432 if (!numsurfacelist)
11434 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11437 // update lightmaps if needed
11441 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11446 R_BuildLightMap(ent, surfaces + j);
11451 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11453 R_BuildLightMap(ent, surfaces + j);
11454 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11456 // add to stats if desired
11457 if (r_speeds.integer && !skysurfaces && !depthonly)
11459 r_refdef.stats.entities_surfaces += numsurfacelist;
11460 for (j = 0;j < numsurfacelist;j++)
11461 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11464 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11467 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11469 static texture_t texture;
11470 static msurface_t surface;
11471 const msurface_t *surfacelist = &surface;
11473 // fake enough texture and surface state to render this geometry
11475 texture.update_lastrenderframe = -1; // regenerate this texture
11476 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11477 texture.currentskinframe = skinframe;
11478 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11479 texture.offsetmapping = OFFSETMAPPING_OFF;
11480 texture.offsetscale = 1;
11481 texture.specularscalemod = 1;
11482 texture.specularpowermod = 1;
11484 surface.texture = &texture;
11485 surface.num_triangles = numtriangles;
11486 surface.num_firsttriangle = firsttriangle;
11487 surface.num_vertices = numvertices;
11488 surface.num_firstvertex = firstvertex;
11491 rsurface.texture = R_GetCurrentTexture(surface.texture);
11492 rsurface.lightmaptexture = NULL;
11493 rsurface.deluxemaptexture = NULL;
11494 rsurface.uselightmaptexture = false;
11495 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11498 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)
11500 static msurface_t surface;
11501 const msurface_t *surfacelist = &surface;
11503 // fake enough texture and surface state to render this geometry
11504 surface.texture = texture;
11505 surface.num_triangles = numtriangles;
11506 surface.num_firsttriangle = firsttriangle;
11507 surface.num_vertices = numvertices;
11508 surface.num_firstvertex = firstvertex;
11511 rsurface.texture = R_GetCurrentTexture(surface.texture);
11512 rsurface.lightmaptexture = NULL;
11513 rsurface.deluxemaptexture = NULL;
11514 rsurface.uselightmaptexture = false;
11515 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);